Module: Aggkit::Ci

Defined in:
lib/aggkit/ci.rb

Instance Method Summary collapse

Instance Method Details

#baseimage(service) ⇒ Object

Базовое имя образа Например harbor.rnds.pro/aggredator/mq



39
40
41
42
43
# File 'lib/aggkit/ci.rb', line 39

def baseimage(service)
  raise "Service name invalid: #{service.inspect}" if service.to_s.length < 2

  "harbor.rnds.pro/aggredator/#{service}"
end

#clean_services(services, tag) ⇒ Object

Растегировать все образы для дальнейшего удаления. Помечает как latest для поддержки кеширования docker



194
195
196
197
198
199
200
201
202
# File 'lib/aggkit/ci.rb', line 194

def clean_services(services, tag)
  [services].flatten.each do |service|
    tagimage! workimage(service, tag), workimage(service, 'latest'), ignoreerror: true
    tagimage! devimage(service, tag), workimage(service, 'latest'), ignoreerror: true
    tagimage! stageimage(service, tag), workimage(service, 'latest'), ignoreerror: true
    tagimage! releaseimage(service, tag), workimage(service, 'latest'), ignoreerror: true
    untagservice(service, tag)
  end
end

#devimage(service, tag) ⇒ Object

Образ с модификатором протестированной автотестами версии Например harbor.rnds.pro/aggredator/mq-dev:7e6420b5



64
65
66
# File 'lib/aggkit/ci.rb', line 64

def devimage(service, tag)
  promotedimage(service, 'dev', tag)
end

#execute(cmd) ⇒ Object



20
21
22
23
24
25
26
27
# File 'lib/aggkit/ci.rb', line 20

def execute(cmd)
  puts "  - executing: #{cmd}"
  result = `#{cmd}`
  puts result
  raise "Execution failed cmd: #{cmd.inspect}" unless $?.success?

  result
end

#info(message) ⇒ Object



16
17
18
# File 'lib/aggkit/ci.rb', line 16

def info(message)
  puts " => #{message}"
end

#label!(image, label, value) ⇒ Object



101
102
103
104
105
106
# File 'lib/aggkit/ci.rb', line 101

def label!(image, label, value)
  raise "Image label invalid: #{label.inspect}" if label.to_s.length < 2
  raise "Image label value invalid: #{value.inspect}" if value.to_s.length < 2

  execute("echo #{image} | docker build -t #{image} --label=\"#{label}=#{value}\" - ")
end

#log_action(action) ⇒ Object



12
13
14
# File 'lib/aggkit/ci.rb', line 12

def log_action(action)
  puts " => #{action}"
end

#promote!(service, tag, stage, fromstage: nil) ⇒ Object

Продвинуть текущий образ сервиса по уровню - добавить модификатор и залить в репозиторий



119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/aggkit/ci.rb', line 119

def promote!(service, tag, stage, fromstage: nil)
  fromimage = if fromstage
    promotedimage(service, fromstage, tag)
  else
    workimage(service, tag)
  end

  toimage = promotedimage(service, stage, tag)

  log_action "Promote #{fromimage} to #{toimage}"
  tagimage! fromimage, toimage, push: true
end

#promote_services_to_dev!(services, tag) ⇒ Object

Продвинуть список образов или упасть с ошибкой



150
151
152
153
154
# File 'lib/aggkit/ci.rb', line 150

def promote_services_to_dev!(services, tag)
  [services].flatten.each do |service|
    promote_to_dev!(service, tag)
  end
end

#promote_services_to_stage!(services, tag) ⇒ Object

Продвинуть список образов или упасть с ошибкой



157
158
159
160
161
# File 'lib/aggkit/ci.rb', line 157

def promote_services_to_stage!(services, tag)
  [services].flatten.each do |service|
    promote_to_stage!(service, tag)
  end
end

#promote_services_to_tag!(services, tag, newtag) ⇒ Object

Протегировать образы до указанного тега



164
165
166
167
168
# File 'lib/aggkit/ci.rb', line 164

def promote_services_to_tag!(services, tag, newtag)
  [services].flatten.each do |service|
    promote_to_tag!(service, tag, newtag)
  end
end

#promote_to_dev!(service, tag) ⇒ Object

Продвинуть текущий образ по уровню - добавить модификатор dev(протестировано) и залить в репозиторий



133
134
135
# File 'lib/aggkit/ci.rb', line 133

def promote_to_dev!(service, tag)
  promote!(service, tag, 'dev')
end

#promote_to_stage!(service, tag) ⇒ Object

Продвинуть текущий образ по уровню - добавить модификатор stage(стабильно) и залить в репозиторий



138
139
140
141
142
# File 'lib/aggkit/ci.rb', line 138

def promote_to_stage!(service, tag)
  promoted = tagimage!(devimage(service, tag), stageimage(service, tag), push: true)
  # Тегируем этот образ как latest
  tagimage!(promoted, stageimage(service, 'latest'), push: true)
end

#promote_to_tag!(service, tag, newtag) ⇒ Object

Продвинуть стабильный образ до указанного тега



145
146
147
# File 'lib/aggkit/ci.rb', line 145

def promote_to_tag!(service, tag, newtag)
  tagimage!(devimage(service, tag), workimage(service, newtag), push: true)
end

#promotedimage(service, stage, tag) ⇒ Object

Образ с модификатором версии Например harbor.rnds.pro/aggredator/mq-dev:7e6420b5



55
56
57
58
59
60
# File 'lib/aggkit/ci.rb', line 55

def promotedimage(service, stage, tag)
  raise "Service stage invalid: #{stage.inspect}" if stage.to_s.length < 2
  raise "Service tag invalid: #{tag.inspect}" if tag.to_s.length < 2

  "#{baseimage(service)}-#{stage}:#{tag}"
end

#pull_images_cache(services, tag) ⇒ Object

Попытаться взять все модификаторы образов из репозитория Скачивает образы и тегирует их как workimage



172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/aggkit/ci.rb', line 172

def pull_images_cache(services, tag)
  log_action "Puling images#{[services].flatten.inspect} from cache...."
  [services].flatten.each do |service|
    execute("docker pull #{workimage(service, tag)} 2> /dev/null || true")
    execute("docker pull #{devimage(service, tag)} 2> /dev/null || true")
    execute("docker pull #{stageimage(service, tag)} 2> /dev/null || true")
    execute("docker pull #{releaseimage(service, tag)} 2> /dev/null || true")
    tagimage! devimage(service, tag), workimage(service, tag), ignoreerror: true
    tagimage! stageimage(service, tag), workimage(service, tag), ignoreerror: true
    tagimage! releaseimage(service, tag), workimage(service, tag), ignoreerror: true
  end
end

#push_images_cache(services, tag) ⇒ Object

Залить образы в репозиторий



186
187
188
189
190
191
# File 'lib/aggkit/ci.rb', line 186

def push_images_cache(services, tag)
  log_action "Pushing images#{[services].flatten.inspect} to cache...."
  [services].flatten.each do |service|
    tagimage! workimage(service, tag), workimage(service, tag), push: true
  end
end

#releaseimage(service, tag) ⇒ Object

Образ с модификатором релизной версии Например harbor.rnds.pro/aggredator/mq-release:7e6420b5



76
77
78
# File 'lib/aggkit/ci.rb', line 76

def releaseimage(service, tag)
  promotedimage(service, 'release', tag)
end

#rmimage!(image) ⇒ Object

Удалить образ образ тегом



96
97
98
99
# File 'lib/aggkit/ci.rb', line 96

def rmimage!(image)
  log_action "Remove #{image.inspect}"
  execute("docker rmi #{image} &> /dev/null || true")
end

#ssh_core_deploy(services, env, sshserver, tag, stage) ⇒ Object



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/aggkit/ci.rb', line 223

def ssh_core_deploy(services, env, sshserver, tag, stage)
  with_remote_docker services, env, sshserver, tag, stage do |config, _environment|
    config_file = config['config_file'].to_s

    execute('docker-compose ps')
    execute('docker-compose pull')
    execute('docker-compose up -t 30 -d consul')

    consul = execute('docker-compose ps | grep consul').split(' ').first.strip
    puts "CONSULT ID: #{consul}"

    unless config_file.empty?
      execute("docker exec -i #{consul} aggwait -t 20 --consul")
      execute("docker exec -i #{consul} aggconsul --init --config - < #{config_file}")
    end

    # echo " * Consul ready"
    # echo " * Updatting database..."
    execute('docker-compose up -t 30 -d db')
    sleep 5
    # echo " * Db ready"
    # echo " * Bootstrapping admin..."
    execute('docker-compose run --rm -T admin /home/app/docker/bootstrap.rb')
    sleep 5
    # echo " * Bootstrapping complete"
    # echo " * Updating all containers..."
    execute('docker-compose up -t 30 -d')
    # echo " * Containers ready"
  end
end

#ssh_deploy(services, env, sshserver, tag, stage) ⇒ Object



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/aggkit/ci.rb', line 204

def ssh_deploy(services, env, sshserver, tag, stage)
  with_remote_docker services, env, sshserver, tag, stage do |config, _environment|
    config_file = config['config_file'].to_s

    execute('docker-compose ps')
    execute('docker-compose pull')

    consul = execute('docker ps --format "{{.ID}}\t{{.Names}}" | grep consul').split(' ').first.strip
    puts "CONSULT ID: #{consul}"

    unless config_file.empty?
      execute("docker exec -i #{consul} aggwait -t 20 --consul")
      execute("docker exec -i #{consul} aggconsul --init --config - < #{config_file}")
    end

    execute('docker-compose up -t 30 -d')
  end
end

#stageimage(service, tag) ⇒ Object

Образ с модификатором стабильной версии Например harbor.rnds.pro/aggredator/mq-stage:7e6420b5



70
71
72
# File 'lib/aggkit/ci.rb', line 70

def stageimage(service, tag)
  promotedimage(service, 'stage', tag)
end

#tagimage!(image, newimage, push: false, ignoreerror: false) ⇒ Object

Протегировать образ тегом



81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/aggkit/ci.rb', line 81

def tagimage!(image, newimage, push: false, ignoreerror: false)
  log_action "Tag #{image.inspect} as #{newimage.inspect}"

  if ignoreerror
    execute("docker tag #{image} #{newimage} 2> /dev/null || true")
  else
    execute("docker tag #{image} #{newimage}")
  end

  execute("docker push #{newimage}") if push

  newimage
end

#untagservice(service, tag) ⇒ Object

Растегировать все модификатора образа сервиса и возможно удалить его



109
110
111
112
113
114
115
116
# File 'lib/aggkit/ci.rb', line 109

def untagservice(service, tag)
  if tag != 'latest'
    rmimage! workimage(service, tag)
    rmimage! devimage(service, tag)
    rmimage! stageimage(service, tag)
    rmimage! releaseimage(service, tag)
  end
end

#with_remote_docker(services, env, sshserver, tag, stage) ⇒ Object



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/aggkit/ci.rb', line 254

def with_remote_docker(services, env, sshserver, tag, stage)
  services = [services].flatten
  log_action "Deploy [#{services.inspect}] tag:#{tag.inspect} stage:#{stage.inspect} to #{sshserver.inspect}"
  with_ssh sshserver do |sockname|
    env_config = JSON(`agg #{env} --show --release`)
    envs = env_config['envs']
    config_file = env_config['config_file'].to_s
    envs['DOCKER_HOST'] = "unix://#{sockname}"
    envs['CORE_TAG'] = tag
    envs['CORE_SUFFIX'] = "-#{stage}"

    localid = execute('docker info | grep ID').strip

    Aggkit::Env.with_env(envs) do |environment|
      remoteid = execute('docker info | grep ID').strip

      raise "Can't get access to remote Docker" if localid == remoteid

      yield(env_config, environment)

      services.each do |service|
        deployed = promotedimage(service, stage, tag)
        current = promotedimage(service, stage, 'current')
        tagimage! deployed, current
        untagservice(service, tag)
      end
    end
  end
end

#with_ssh(server, user: 'root') ⇒ Object



284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/aggkit/ci.rb', line 284

def with_ssh(server, user: 'root')
  file = Tempfile.new
  @ssh_sockname = file.path
  file.unlink
  @ssh_pid = spawn("ssh -NL #{@ssh_sockname}:/var/run/docker.sock root@#{server}")
  sleep 5
  yield(@ssh_sockname)
ensure
  Process.kill(:SIGTERM, @ssh_pid)
  sleep 5
  Process.wait2(@ssh_pid, Process::WNOHANG)
  FileUtils.rm_f(@ssh_sockname)
end

#workimage(service, tag) ⇒ Object

Текущее имя образа без модификаторов продвижения, но с тегом Например harbor.rnds.pro/aggredator/mq:7e6420b5



47
48
49
50
51
# File 'lib/aggkit/ci.rb', line 47

def workimage(service, tag)
  raise "Service tag invalid: #{tag.inspect}" if tag.to_s.length < 2

  "#{baseimage(service)}:#{tag}"
end