summaryrefslogtreecommitdiff
path: root/lib/container_registry/tag.rb
blob: 76188a937c0f18f9613b858d0965eb81d15aea9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# frozen_string_literal: true

module ContainerRegistry
  class Tag
    include Gitlab::Utils::StrongMemoize

    attr_reader :repository, :name
    attr_writer :created_at

    delegate :registry, :client, to: :repository
    delegate :revision, :short_revision, to: :config_blob, allow_nil: true

    def initialize(repository, name)
      @repository = repository
      @name = name
    end

    def valid?
      manifest.present?
    end

    def latest?
      name == "latest"
    end

    def v1?
      manifest && manifest['schemaVersion'] == 1
    end

    def v2?
      manifest && manifest['schemaVersion'] == 2
    end

    def manifest
      strong_memoize(:manifest) do
        client.repository_manifest(repository.path, name)
      end
    end

    def path
      "#{repository.path}:#{name}"
    end

    def location
      "#{repository.location}:#{name}"
    end

    def [](key)
      return unless manifest

      manifest[key]
    end

    def digest
      strong_memoize(:digest) do
        client.repository_tag_digest(repository.path, name)
      end
    end

    def config_blob
      return unless manifest && manifest['config']

      strong_memoize(:config_blob) do
        repository.blob(manifest['config'])
      end
    end

    def config
      return unless config_blob&.data

      strong_memoize(:config) do
        ContainerRegistry::Config.new(self, config_blob)
      end
    end

    def created_at
      return @created_at if @created_at

      strong_memoize(:memoized_created_at) do
        next unless config

        DateTime.rfc3339(config['created'])
      rescue ArgumentError
        nil
      end
    end

    # this function will set and memoize a created_at
    # to avoid a #config_blob call.
    def force_created_at_from_iso8601(string_value)
      date =
        begin
          DateTime.iso8601(string_value)
        rescue ArgumentError
          nil
        end
      instance_variable_set(ivar(:memoized_created_at), date)
    end

    def layers
      return unless manifest

      strong_memoize(:layers) do
        layers = manifest['layers'] || manifest['fsLayers']

        layers.map do |layer|
          repository.blob(layer)
        end
      end
    end

    def put(digests)
      repository.client.put_tag(repository.path, name, digests)
    end

    # rubocop: disable CodeReuse/ActiveRecord
    def total_size
      return unless layers

      layers.sum(&:size) if v2?
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # Deletes the image associated with this tag
    # Note this will delete the image and all tags associated with it.
    # Consider using DeleteTagsService instead.
    def unsafe_delete
      return unless digest

      client.delete_repository_tag_by_digest(repository.path, digest)
    end
  end
end