takelage 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ab8abe1d25c97442acec36bb9ab580d2c49efb64572ececd587f4caa7ab30892
4
- data.tar.gz: 49253eba927e0091bcc151d6f20424df56436df23c97669f18654202a7d40257
3
+ metadata.gz: 8addb80341d57218461d5625ae970eadf0999a62f90751856ce8c7be3c5ae0f4
4
+ data.tar.gz: 4f04e5223e1d79ea612018d61cc541a965cb65806133db9e233d31133791ed16
5
5
  SHA512:
6
- metadata.gz: e8c69a6cbe268b971f2eb07b786cf3b6f4ea8d333dd0e8c047bbdc5394727fc3a6e3b35cbb03bac3676c3b1ce5d4eda64d71c990ffff2d49c43d95967d4cdd8d
7
- data.tar.gz: f643e564fe3db829fad180f9948cc2381782c5410efa9d2386e05f7bc9cc0d45ff50ff24c7a4586a838e8f3e6c369eac445a2aa6db4bb97609371347060d8bdd
6
+ metadata.gz: 4e90bb0a41ab5642afed06094fa6d70038651701778dcc91a41d3f7fa6ece70e60f42860dd50778b049cf11bb5b4b34f40471934e36c47b851501cf081f5c722
7
+ data.tar.gz: caefc99ff51fa28769d6801347cccc320ceb5434573013dca2c0638749d8a548f54c0f585513b24dcb90decf4f7d674c4917aa642710fb4e0b5925d2b60d7be8
data/README.md CHANGED
@@ -53,19 +53,20 @@ tau [bit clipboard paste](features/takelage/bit/bit.clipboard.paste.feature) [CO
53
53
  tau [bit clipboard pull](features/takelage/bit/bit.clipboard.pull.feature) | Pull all updates for bit components from bit remote scopes
54
54
  tau [bit clipboard push](features/takelage/bit/bit.clipboard.push.feature) | Push all updates of bit components to bit remote scopes
55
55
  tau [bit scope add](features/takelage/bit/bit.scope.add.feature) [SCOPE] | Add a bit [SCOPE]
56
- tau [bit scope list](features/takelage/bit/bit.scope.list.feature) | List bit remote scopes
57
56
  tau [bit scope inbit](features/takelage/bit/bit.scope.inbit.feature) | Log in to bit remote server
57
+ tau [bit scope list](features/takelage/bit/bit.scope.list.feature) | List bit remote scopes
58
58
  tau [bit scope new](features/takelage/bit/bit.scope.new.feature) [SCOPE] | Init a new bit [SCOPE]
59
59
  tau [completion bash](features/takelage/completion/completion.bash.feature) | Print bash completion code
60
60
  tau [docker check running](features/takelage/docker/docker.check.running.feature) | Check if docker daemon is running
61
61
  tau [docker container check existing](features/takelage/docker/docker.container.check.existing.feature) [CONTAINER] | Check if docker [CONTAINER] is existing
62
- tau [docker container check orphaned](features/takelage/docker/docker.container.check.orphaned.feature) [CONTAINER] | Check if docker [CONTAINER] is orphaned
63
62
  tau [docker container check network](features/takelage/docker/docker.container.check.network.feature) [NETWORK] | Check if docker [NETWORK] is existing
63
+ tau [docker container check orphaned](features/takelage/docker/docker.container.check.orphaned.feature) [CONTAINER] | Check if docker [CONTAINER] is orphaned
64
64
  tau [docker container command](features/takelage/docker/docker.container.command.feature) [CMD] | Run [CMD] in a docker container
65
65
  tau [docker container daemon](features/takelage/docker/docker.container.daemon.feature) | Run docker container in daemon mode
66
66
  tau [docker container login](features/takelage/docker/docker.container.login.feature) | Log in to latest local docker container
67
67
  tau [docker container nuke](features/takelage/docker/docker.container.nuke.feature) | Remove all docker containers
68
68
  tau [docker container purge](features/takelage/docker/docker.container.purge.feature) | Remove orphaned docker containers
69
+ tau [docker image check outdated](features/takelage/docker/docker.image.check.outdated.feature) | Check if a docker image is outdated
69
70
  tau [docker image tag check local](features/takelage/docker/docker.image.tag.check.local.feature) [TAG] | Check if local docker image [TAG] exists
70
71
  tau [docker image tag check remote](features/takelage/docker/docker.image.tag.check.remote.feature) [TAG] | Check if remote docker image [TAG] exists
71
72
  tau [docker image tag latest local](features/takelage/docker/docker.image.tag.latest.local.feature) | Print latest local docker image tag
@@ -73,14 +74,16 @@ tau [docker image tag latest remote](features/takelage/docker/docker.image.tag.l
73
74
  tau [docker image tag list local](features/takelage/docker/docker.image.tag.list.local.feature) | Print local docker image tags
74
75
  tau [docker image tag list remote](features/takelage/docker/docker.image.tag.list.remote.feature) | Print remote docker image tags
75
76
  tau [docker image update](features/takelage/docker/docker.image.update.feature) | Get latest remote docker container
77
+ tau [docker socket host](features/takelage/docker/docker.socket.host.feature) | Print docker socket host ip address
78
+ tau [docker socket scheme](features/takelage/docker/docker.socket.scheme.feature) | Print docker socket scheme
76
79
  tau [docker socket start](features/takelage/docker/docker.socket.start.feature) | Start sockets for docker container
77
80
  tau [docker socket stop](features/takelage/docker/docker.socket.stop.feature) | Stop sockets for docker container
78
81
  tau [git check clean](features/takelage/git/git.check.clean.feature) | Check if the git workspace is clean
79
82
  tau [git check master](features/takelage/git/git.check.master.feature) | Check if we are on the git master branch
80
83
  tau [git check workspace](features/takelage/git/git.check.workspace.feature) | Check if a git workspace exists
81
84
  tau [info project active](features/takelage/info/info.project.active.feature) | Print active project info
82
- tau [info project private](features/takelage/info/info.project.private.feature) | Print private project info
83
85
  tau [info project main](features/takelage/info/info.project.main.feature) | Print main project info
86
+ tau [info project private](features/takelage/info/info.project.private.feature) | Print private project info
84
87
  tau [self config active](features/takelage/self/self.config.active.feature) | Print active takelage configuration
85
88
  tau [self config default](features/takelage/self/self.config.default.feature) | Print takelage default configuration
86
89
  tau [self config home](features/takelage/self/self.config.home.feature) | Print takelage home config file configuration
@@ -23,7 +23,7 @@ cmd_docker_check_running_docker_info: 'docker info'
23
23
  cmd_docker_container_check_existing_docker_ps: 'docker ps --filter name=^%{container}$ --quiet'
24
24
  cmd_docker_container_check_network_docker_network: 'docker network ls --quiet --filter name=^%{network}$'
25
25
  cmd_docker_container_check_orphaned_docker_exec: 'docker exec --interactive %{container} ps a'
26
- cmd_docker_container_create: 'docker run --detach --env GOOGLE_APPLICATION_CREDENTIALS=/srv/google/default.json --env TAKELAGE_PROJECT_BASE_DIR=%{workdir} --env TZ=%{timezone} --hostname %{container} --name %{container} --network %{container} --privileged --rm --tty --volume %{dockersock}:/var/run/docker.sock --volume %{homedir}/.config/gcloud:/srv/gcloud --volume %{homedir}/.google:/srv/google --volume %{homedir}:/homedir --volume %{workdir}:/project %{volume_dev} --workdir /project %{image} %{entrypoint} --gid %{gid} --home %{homedir} --uid %{uid} --username %{username} %{entrypoint_options}'
26
+ cmd_docker_container_create: 'docker run %{addhost} --detach --env GOOGLE_APPLICATION_CREDENTIALS=/srv/google/default.json --env TAKELAGE_PROJECT_BASE_DIR=%{workdir} --env TZ=%{timezone} --hostname %{container} --name %{container} --network %{container} --privileged --rm --tty --volume %{dockersock}:/var/run/docker.sock --volume %{homedir}/.config/gcloud:/srv/gcloud --volume %{homedir}/.google:/srv/google --volume %{homedir}:/homedir --volume %{workdir}:/project %{volume_dev} --workdir /project %{image} %{entrypoint} --gid %{gid} --home %{homedir} --uid %{uid} --username %{username} %{entrypoint_options}'
27
27
  cmd_docker_container_create_network: 'docker network create %{network}'
28
28
  cmd_docker_container_enter_container: 'docker exec --interactive --tty %{container} %{loginpoint} --username %{username}'
29
29
  cmd_docker_container_get_container_name: 'docker ps --filter id=%{container} --format "{{.Names}}"'
@@ -36,8 +36,9 @@ cmd_docker_image_tag_list_local_docker_images: 'docker images %{docker_user}\/%{
36
36
  cmd_docker_image_update_docker_pull_latest: 'docker pull %{docker_user}/%{docker_repo}:%{tag_latest_remote}'
37
37
  cmd_docker_socket_stop_docker_socket_ps: 'sudo ps a -o pid,command'
38
38
  cmd_docker_socket_stop_docker_socket_kill: 'sudo kill -SIGTERM %{pid}'
39
- cmd_docker_socket_get_socket_socat: 'sudo socat TCP-LISTEN:%{port},bind=%{host},reuseaddr,fork UNIX-CLIENT:%{path}'
40
- cmd_docker_socket_get_socket_gpgconf: 'gpgconf --list-dirs'
39
+ cmd_docker_socket_get_start: 'sudo socat TCP-LISTEN:%{port},bind=%{host},reuseaddr,fork UNIX-CLIENT:%{path}'
40
+ cmd_docker_socket_config_agent_socket_path: 'gpgconf --list-dirs agent-socket'
41
+ cmd_docker_socket_config_agent_ssh_socket_path: 'gpgconf --list-dirs agent-ssh-socket'
41
42
  cmd_docker_socket_start_sudo_true: 'sudo true'
42
43
  cmd_git_check_clean_git_unstaged: 'git diff --exit-code'
43
44
  cmd_git_check_clean_git_uncommitted: 'git diff --cached --exit-code'
@@ -49,10 +50,8 @@ docker_debug: 'ansible/roles/takel-takelage/files/pyscripts'
49
50
  docker_entrypoint_options: ''
50
51
  docker_registry: 'https://registry.hub.docker.com'
51
52
  docker_repo: 'takelage'
52
- docker_socket_agent_port: 20000
53
- docker_socket_agent_ssh_port: 20001
54
- docker_socket_agent_extra_port: 20002
55
- docker_socket_agent_browser_port: 20003
53
+ docker_socket_agent_socket_port: 20000
54
+ docker_socket_agent_ssh_socket_port: 20001
56
55
  docker_tag: 'latest'
57
56
  docker_user: 'takelage'
58
57
  info_project_main: 'project.yml'
@@ -12,9 +12,10 @@ module Takelage
12
12
  include DockerImageTagLatestModule
13
13
  include DockerImageTagListModule
14
14
  include DockerImageTagCheckModule
15
+ include DockerImageCheckModule
15
16
  include DockerSocketModule
16
17
 
17
- # Initialize takelage docker container
18
+ # Initialize docker container
18
19
  def initialize(args=[], local_options={}, configuration={})
19
20
 
20
21
  # initialize thor parent class
@@ -40,24 +41,8 @@ module Takelage
40
41
 
41
42
  @timezone = 'Europe/Berlin'
42
43
 
43
- @sockets = {
44
- :'agent-socket' => {
45
- :path => nil,
46
- :host => '127.0.0.1',
47
- :port => config.active['docker_socket_agent_port']},
48
- :'agent-ssh-socket' => {
49
- :path => nil,
50
- :host => '127.0.0.1',
51
- :port => config.active['docker_socket_agent_ssh_port']},
52
- :'agent-extra-socket' => {
53
- :path => nil,
54
- :host => '127.0.0.1',
55
- :port => config.active['docker_socket_agent_extra_port']},
56
- :'agent-browser-socket' => {
57
- :path => nil,
58
- :host => '127.0.0.1',
59
- :port => config.active['docker_socket_agent_browser_port']}}
60
- _get_socket_paths
44
+ @socket_host = docker_socket_host
45
+ @sockets = docker_socket_scheme
61
46
  end
62
47
 
63
48
  desc 'check [COMMAND]', 'Check docker container'
@@ -30,6 +30,15 @@ module DockerContainerModule
30
30
 
31
31
  return false unless docker_check_running
32
32
 
33
+ unless @docker_tag == 'latest'
34
+ outdated = docker_image_check_outdated @docker_tag
35
+ if outdated
36
+ tag_latest_remote = docker_image_tag_latest_remote
37
+ say "Your takelage version \"#{@docker_tag}\" is outdated"
38
+ say "A new takelage version \"#{tag_latest_remote}\" is available"
39
+ end
40
+ end
41
+
33
42
  docker_socket_start
34
43
 
35
44
  _create_network @hostname unless docker_container_check_network @hostname
@@ -96,6 +105,10 @@ module DockerContainerModule
96
105
  return false
97
106
  end
98
107
 
108
+ unless @socket_host == '127.0.0.1'
109
+ addhost = "--add-host host.docker.internal:#{@socket_host}"
110
+ end
111
+
99
112
  entrypoint = '/entrypoint.py '
100
113
  volume_dev = ''
101
114
  if options[:development]
@@ -105,6 +118,7 @@ module DockerContainerModule
105
118
 
106
119
  cmd_docker_create =
107
120
  config.active['cmd_docker_container_create'] % {
121
+ addhost: addhost,
108
122
  workdir: @workdir,
109
123
  timezone: @timezone,
110
124
  container: container,
@@ -0,0 +1,40 @@
1
+ module Takelage
2
+
3
+ # takelage docker image check
4
+ class DockerImageCheck < SubCommandBase
5
+
6
+ include LoggingModule
7
+ include SystemModule
8
+ include ConfigModule
9
+ include DockerCheckModule
10
+ include DockerImageTagListModule
11
+ include DockerImageTagLatestModule
12
+ include DockerImageCheckModule
13
+
14
+ # Initialize takelage docker image check
15
+ def initialize(args = [], local_options = {}, configuration = {})
16
+
17
+ # initialize thor parent class
18
+ super args, local_options, configuration
19
+
20
+ @docker_user = config.active['docker_user']
21
+ @docker_repo = config.active['docker_repo']
22
+ @docker_registry = config.active['docker_registry']
23
+ @docker_tag = config.active['docker_tag']
24
+ end
25
+
26
+ #
27
+ # docker image check outdated
28
+ #
29
+ desc 'outdated', 'Check if a docker image is outdated'
30
+ long_desc <<-LONGDESC.gsub("\n", "\x5")
31
+ Check if a docker image is outdated
32
+ LONGDESC
33
+ # Check if a docker image is outdated.
34
+ def outdated
35
+ outdated = docker_image_check_outdated @docker_tag
36
+ say "Your takelage version \"#{@docker_tag}\" is outdated" if outdated
37
+ exit outdated
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,27 @@
1
+ # takelage docker image check module
2
+ module DockerImageCheckModule
3
+
4
+ # Backend method for docker image check outdated.
5
+ # @return [Boolean] is docker image tag older than latest remote docker image tag?
6
+ def docker_image_check_outdated(tag)
7
+ log.debug "Check if docker image version \"#{tag}\" is outdated"
8
+
9
+ return false unless docker_check_running
10
+
11
+ if tag == 'latest'
12
+ log.debug "Docker image version \"latest\" is by definition never outdated"
13
+ return false
14
+ end
15
+
16
+ tag_latest_remote = docker_image_tag_latest_remote
17
+ tags = [tag, tag_latest_remote]
18
+ outdated = tag != VersionSorter.sort(tags).last
19
+
20
+ if outdated
21
+ "Docker image version \"#{tag}\" is outdated"
22
+ "Docker image version \"#{tag_latest_remote}\" is available"
23
+ end
24
+
25
+ outdated
26
+ end
27
+ end
@@ -22,6 +22,9 @@ module Takelage
22
22
  @docker_registry = config.active['docker_registry']
23
23
  end
24
24
 
25
+ desc 'check [COMMAND]', 'Check docker image'
26
+ subcommand 'check', DockerImageCheck
27
+
25
28
  desc 'tag [COMMAND]', 'Handle docker image tags'
26
29
  subcommand 'tag', DockerImageTag
27
30
 
@@ -4,8 +4,8 @@ module Takelage
4
4
  class DockerSocket < SubCommandBase
5
5
 
6
6
  include LoggingModule
7
- include ConfigModule
8
7
  include SystemModule
8
+ include ConfigModule
9
9
  include DockerCheckModule
10
10
  include DockerSocketModule
11
11
 
@@ -15,24 +15,34 @@ module Takelage
15
15
  # initialize thor parent class
16
16
  super args, local_options, configuration
17
17
 
18
- @sockets = {
19
- :'agent-socket' => {
20
- :path => nil,
21
- :host => '127.0.0.1',
22
- :port => config.active['docker_socket_agent_port']},
23
- :'agent-ssh-socket' => {
24
- :path => nil,
25
- :host => '127.0.0.1',
26
- :port => config.active['docker_socket_agent_ssh_port']},
27
- :'agent-extra-socket' => {
28
- :path => nil,
29
- :host => '127.0.0.1',
30
- :port => config.active['docker_socket_agent_extra_port']},
31
- :'agent-browser-socket' => {
32
- :path => nil,
33
- :host => '127.0.0.1',
34
- :port => config.active['docker_socket_agent_browser_port']}}
35
- _get_socket_paths
18
+ @socket_host = docker_socket_host
19
+ @sockets = docker_socket_scheme
20
+ end
21
+
22
+ #
23
+ # docker socket host
24
+ #
25
+ desc 'host', 'Print docker socket host ip address'
26
+ long_desc <<-LONGDESC.gsub("\n", "\x5")
27
+ Print docker socket host ip address
28
+ LONGDESC
29
+ # Print docker socket host ip address.
30
+ def host
31
+ say @socket_host
32
+ true
33
+ end
34
+
35
+ #
36
+ # docker socket scheme
37
+ #
38
+ desc 'scheme', 'Print docker socket scheme'
39
+ long_desc <<-LONGDESC.gsub("\n", "\x5")
40
+ Print docker socket scheme
41
+ LONGDESC
42
+ # Print docker socket scheme.
43
+ def scheme
44
+ say hash_to_yaml(@sockets)
45
+ true
36
46
  end
37
47
 
38
48
  #
@@ -1,6 +1,67 @@
1
1
  # takelage docker socket module
2
2
  module DockerSocketModule
3
3
 
4
+ # Backend method for docker socket scheme.
5
+ def docker_socket_scheme
6
+ log.debug 'Getting docker socket scheme'
7
+
8
+ cmd_agent_socket_path =
9
+ config.active['cmd_docker_socket_config_agent_socket_path']
10
+
11
+ agent_socket_path = run cmd_agent_socket_path
12
+ agent_socket_path.chomp!
13
+
14
+ agent_socket_port =
15
+ config.active['docker_socket_agent_socket_port']
16
+
17
+ cmd_agent_ssh_socket_path =
18
+ config.active['cmd_docker_socket_config_agent_ssh_socket_path']
19
+
20
+ agent_ssh_socket_path = run cmd_agent_ssh_socket_path
21
+ agent_ssh_socket_path.chomp!
22
+
23
+ agent_ssh_socket_port =
24
+ config.active['docker_socket_agent_ssh_socket_port']
25
+
26
+ socket_scheme = {
27
+ 'agent-socket' => {
28
+ 'path' => agent_socket_path,
29
+ 'host' => @socket_host,
30
+ 'port' => agent_socket_port
31
+ },
32
+ 'agent-ssh-socket' => {
33
+ 'path' => agent_ssh_socket_path,
34
+ 'host' => @socket_host,
35
+ 'port' => agent_ssh_socket_port
36
+ }
37
+ }
38
+
39
+ log.debug "Docker socket scheme is \n\"\"\"\n#{hash_to_yaml socket_scheme}\"\"\""
40
+
41
+ socket_scheme
42
+ end
43
+
44
+ # Backend method for docker socket host.
45
+ def docker_socket_host
46
+ log.debug 'Getting docker socket host ip address'
47
+
48
+ socket_host = '127.0.0.1'
49
+
50
+ addr_infos = Socket.getifaddrs
51
+
52
+ # if interface docker0 exists (== linux host)
53
+ # then return the ip address
54
+ addr_infos.each do |addr_info|
55
+ if addr_info.name == 'docker0'
56
+ socket_host = addr_info.addr.ip_address if addr_info.addr.ipv4?
57
+ end
58
+ end
59
+
60
+ log.debug "Docker socket host ip address is \"#{socket_host}\""
61
+
62
+ socket_host
63
+ end
64
+
4
65
  # Backend method for docker socket start.
5
66
  def docker_socket_start
6
67
  log.debug 'Starting sockets for docker container'
@@ -76,11 +137,11 @@ module DockerSocketModule
76
137
  # loop over sockets
77
138
  @sockets.each do |socket, socket_config|
78
139
  cmd_start_socket =
79
- config.active['cmd_docker_socket_get_socket_socat'] % {
80
- host: socket_config[:host],
81
- port: socket_config[:port],
82
- path: socket_config[:path],
83
- }
140
+ config.active['cmd_docker_socket_get_start'] % {
141
+ port: socket_config['port'],
142
+ host: socket_config['host'],
143
+ path: socket_config['path'],
144
+ }
84
145
 
85
146
  if sockets_up
86
147
  if _socket_up? socket, socket_config
@@ -96,29 +157,12 @@ module DockerSocketModule
96
157
  cmds_start_socket
97
158
  end
98
159
 
99
- # get socket paths
100
- def _get_socket_paths
101
- cmd_gpgconf_listdirs =
102
- config.active['cmd_docker_socket_get_socket_gpgconf']
103
-
104
- stdout_str = run cmd_gpgconf_listdirs
105
-
106
- stdout_str.split(/\n+/).each do |gpg_path|
107
- @sockets.each do |socket, socket_config|
108
- gpg_socket = gpg_path.split(':')
109
- if gpg_socket[0] == socket.to_s
110
- @sockets[socket][:path] = gpg_socket[1]
111
- end
112
- end
113
- end
114
- end
115
-
116
160
  # check if a socket is available
117
161
  # but trying to connect to it via TCP
118
162
  def _socket_up? socket, socket_config
119
- host = socket_config[:host]
120
- port = socket_config[:port]
121
- path = socket_config[:path]
163
+ host = socket_config['host']
164
+ port = socket_config['port']
165
+ path = socket_config['path']
122
166
 
123
167
  error_message = "failed to connect to " +
124
168
  "socket \"#{socket}\" " +
@@ -11,7 +11,7 @@ module SystemModule
11
11
  if hash == {}
12
12
  return nil.to_yaml
13
13
  end
14
- return hash.to_yaml(options = {:line_width => -1})
14
+ hash.to_yaml(options = {:line_width => -1})
15
15
  end
16
16
 
17
17
  # @return [Hash] content of yaml file
data/lib/takelage/version CHANGED
@@ -1 +1 @@
1
- 0.10.0
1
+ 0.11.0
data/lib/takelage.rb CHANGED
@@ -39,6 +39,8 @@ require_relative 'takelage/docker/image/tag/latest/cli'
39
39
  require_relative 'takelage/docker/image/tag/check/module'
40
40
  require_relative 'takelage/docker/image/tag/check/cli'
41
41
  require_relative 'takelage/docker/image/tag/cli'
42
+ require_relative 'takelage/docker/image/check/module'
43
+ require_relative 'takelage/docker/image/check/cli'
42
44
  require_relative 'takelage/docker/image/module'
43
45
  require_relative 'takelage/docker/image/cli'
44
46
  require_relative 'takelage/docker/container/check/module'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: takelage
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geospin
@@ -221,6 +221,8 @@ files:
221
221
  - lib/takelage/docker/container/check/module.rb
222
222
  - lib/takelage/docker/container/cli.rb
223
223
  - lib/takelage/docker/container/module.rb
224
+ - lib/takelage/docker/image/check/cli.rb
225
+ - lib/takelage/docker/image/check/module.rb
224
226
  - lib/takelage/docker/image/cli.rb
225
227
  - lib/takelage/docker/image/module.rb
226
228
  - lib/takelage/docker/image/tag/check/cli.rb