Class: DockerRegistry2::Registry

Inherits:
Object
  • Object
show all
Defined in:
lib/registry/registry.rb

Instance Method Summary collapse

Constructor Details

#initialize(uri, options = {}) ⇒ Registry

Returns a new instance of Registry.

Parameters:

  • base_uri (#to_s)

    Docker registry base URI

  • options (Hash) (defaults to: {})

    Client options

Options Hash (options):

  • :user (#to_s)

    User name for basic authentication

  • :password (#to_s)

    Password for basic authentication

  • :open_timeout (#to_s)

    Time to wait for a connection with a registry

  • :read_timeout (#to_s)

    Time to wait for data from a registry



12
13
14
15
16
17
18
19
# File 'lib/registry/registry.rb', line 12

def initialize(uri, options = {})
  @uri = URI.parse(uri)
  @base_uri = "#{@uri.scheme}://#{@uri.host}:#{@uri.port}"
  @user = options[:user]
  @password = options[:password]
  @open_timeout = options[:open_timeout] || 2
  @read_timeout = options[:read_timeout] || 5
end

Instance Method Details

#_pull_v1(repo, manifest, dir) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/registry/registry.rb', line 134

def _pull_v1(repo, manifest, dir)
  # make sure the directory exists
  FileUtils.mkdir_p dir
  return false unless manifest['schemaVersion'] == 1
  # pull each of the layers
  manifest['fsLayers'].each do |layer|
    # define path of file to save layer in
    layer_file = "#{dir}/#{layer['blobSum']}"
    # skip layer if we already got it
    next if File.file? layer_file
    # download layer
    # puts "getting layer (v1) #{layer['blobSum']}"
    File.open(layer_file, 'w') do |fd|
      doreq('get',
            "/v2/#{repo}/blobs/#{layer['blobSum']}",
            fd)
    end
    # return layer file
    layer_file
  end
end

#_pull_v2(repo, manifest, dir) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/registry/registry.rb', line 113

def _pull_v2(repo, manifest, dir)
  # make sure the directory exists
  FileUtils.mkdir_p dir
  return false unless manifest['schemaVersion'] == 2
  # pull each of the layers
  manifest['layers'].each do |layer|
    # define path of file to save layer in
    layer_file = "#{dir}/#{layer['digest']}"
    # skip layer if we already got it
    next if File.file? layer_file
    # download layer
    # puts "getting layer (v2) #{layer['digest']}"
    File.open(layer_file, 'w') do |fd|
      doreq('get',
            "/v2/#{repo}/blobs/#{layer['digest']}",
            fd)
    end
    layer_file
  end
end

#blob_size(repo, blobSum) ⇒ Object

gets the size of a particular blob, given the repo and the content-addressable hash usually unneeded, since manifest includes it



174
175
176
177
# File 'lib/registry/registry.rb', line 174

def blob_size(repo,blobSum)
  response = dohead "/v2/#{repo}/blobs/#{blobSum}"
  Integer(response.headers[:content_length],10)
end

#copy(repo, tag, newregistry, newrepo, newtag) ⇒ Object



169
170
# File 'lib/registry/registry.rb', line 169

def copy(repo,tag,newregistry,newrepo,newtag)
end

#digest(repo, tag) ⇒ Object



84
85
86
87
88
89
90
# File 'lib/registry/registry.rb', line 84

def digest(repo, tag)
  tag_path = "/v2/#{repo}/manifests/#{tag}"
  dohead(tag_path).headers[:docker_content_digest]
rescue DockerRegistry2::InvalidMethod
  # Pre-2.3.0 registries didn't support manifest HEAD requests
  doget(tag_path).headers[:docker_content_digest]
end

#dodelete(url) ⇒ Object



29
30
31
# File 'lib/registry/registry.rb', line 29

def dodelete(url)
  return doreq "delete", url
end

#doget(url) ⇒ Object



21
22
23
# File 'lib/registry/registry.rb', line 21

def doget(url)
  return doreq "get", url
end

#dohead(url) ⇒ Object



33
34
35
# File 'lib/registry/registry.rb', line 33

def dohead(url)
  return doreq "head", url
end

#doput(url, payload = nil) ⇒ Object



25
26
27
# File 'lib/registry/registry.rb', line 25

def doput(url,payload=nil)
  return doreq "put", url, nil, payload
end

#manifest(repo, tag) ⇒ Object



79
80
81
82
# File 'lib/registry/registry.rb', line 79

def manifest(repo,tag)
  # first get the manifest
  JSON.parse doget "/v2/#{repo}/manifests/#{tag}"
end

#manifest_sum(manifest) ⇒ Object



179
180
181
182
183
184
185
# File 'lib/registry/registry.rb', line 179

def manifest_sum(manifest)
  size = 0
  manifest["layers"].each { |layer|
    size += layer["size"]
  }
  size
end

#pingObject



37
38
39
# File 'lib/registry/registry.rb', line 37

def ping
  response = doget '/v2/'
end

#pull(repo, tag, dir) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/registry/registry.rb', line 99

def pull(repo, tag, dir)
  # make sure the directory exists
  FileUtils.mkdir_p dir
  # get the manifest
  m = manifest repo, tag
  # puts "pulling #{repo}:#{tag} into #{dir}"
  # manifest can contain multiple manifests one for each API version
  downloaded_layers = []
  downloaded_layers += _pull_v2(repo, m, dir) if m['schemaVersion'] == 2
  downloaded_layers += _pull_v1(repo, m, dir) if m['schemaVersion'] == 1
  # return downloaded_layers
  downloaded_layers
end

#push(manifest, dir) ⇒ Object



156
157
# File 'lib/registry/registry.rb', line 156

def push(manifest,dir)
end

#rmtag(image, tag) ⇒ Object



92
93
94
95
96
97
# File 'lib/registry/registry.rb', line 92

def rmtag(image, tag)
  # TODO: Need full response back. Rewrite other manifests() calls without JSON?
  reference = doget("/v2/#{image}/manifests/#{tag}").headers[:docker_content_digest]

  return dodelete("/v2/#{image}/manifests/#{reference}").code
end

#search(query = '') ⇒ Object



41
42
43
44
45
46
47
48
49
50
# File 'lib/registry/registry.rb', line 41

def search(query = '')
  response = doget "/v2/_catalog"
  # parse the response
  repos = JSON.parse(response)["repositories"]
  if query.strip.length > 0
    re = Regexp.new query
    repos = repos.find_all {|e| re =~ e }
  end
  return repos
end

#tag(repo, tag, newrepo, newtag) ⇒ Object



159
160
161
162
163
164
165
166
167
# File 'lib/registry/registry.rb', line 159

def tag(repo,tag,newrepo,newtag)
  manifest = manifest(repo, tag)

  if manifest['schemaVersion'] == 2
    doput "/v2/#{newrepo}/manifests/#{newtag}", manifest.to_json
  else
    raise DockerRegistry2::RegistryVersionException
  end
end

#tags(repo, withHashes = false) ⇒ Object



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
# File 'lib/registry/registry.rb', line 52

def tags(repo,withHashes = false)
  response = doget "/v2/#{repo}/tags/list"
  # parse the response
  resp = JSON.parse response
  # do we include the hashes?
  if withHashes then
    useGet = false
    resp["hashes"] = {}
    resp["tags"].each {|tag|
      if useGet then
        head = doget "/v2/#{repo}/manifests/#{tag}"
      else
        begin
          head = dohead "/v2/#{repo}/manifests/#{tag}"
        rescue DockerRegistry2::InvalidMethod
          # in case we are in a registry pre-2.3.0, which did not support manifest HEAD
          useGet = true
          head = doget "/v2/#{repo}/manifests/#{tag}"
        end
      end
      resp["hashes"][tag] = head.headers[:docker_content_digest]
    }
  end

  return resp
end