picsolve_docker_builder 0.1.1 → 0.2.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/README.md +45 -2
  4. data/integration/compose_hello_world_new_config/.docker-builder.yml +18 -0
  5. data/integration/compose_hello_world_new_config/.gitignore +1 -0
  6. data/integration/compose_hello_world_new_config/Gemfile +2 -0
  7. data/integration/compose_hello_world_new_config/Rakefile +3 -0
  8. data/integration/compose_hello_world_old_config/.docker-builder.yml +4 -0
  9. data/integration/compose_hello_world_old_config/.gitignore +1 -0
  10. data/integration/compose_hello_world_old_config/Gemfile +2 -0
  11. data/integration/compose_hello_world_old_config/Rakefile +3 -0
  12. data/integration/compose_hello_world_old_config/docker-compose.yml +4 -0
  13. data/integration/integration_compose_spec.rb +25 -0
  14. data/integration/integration_helpers.rb +45 -0
  15. data/integration/integration_play_spec.rb +4 -38
  16. data/integration/lib_hello_world/.gitignore +12 -0
  17. data/integration/lib_hello_world/README +4 -0
  18. data/integration/lib_hello_world/app/picsolve/helloworld/Person.scala +8 -0
  19. data/integration/lib_hello_world/build.sbt +42 -0
  20. data/integration/lib_hello_world/conf/application.conf +0 -0
  21. data/integration/lib_hello_world/conf/logback.xml +22 -0
  22. data/integration/lib_hello_world/project/build.properties +4 -0
  23. data/integration/lib_hello_world/project/plugins.sbt +4 -0
  24. data/integration/lib_hello_world/test/PersonSpec.scala +24 -0
  25. data/integration/lib_hello_world/version.sbt +1 -0
  26. data/integration/spec_helper.rb +2 -0
  27. data/lib/picsolve_docker_builder/builder/builder.rb +4 -2
  28. data/lib/picsolve_docker_builder/composer/composer.rb +45 -74
  29. data/lib/picsolve_docker_builder/composer/container.rb +79 -0
  30. data/lib/picsolve_docker_builder/composer/image.rb +10 -8
  31. data/lib/picsolve_docker_builder/frame.rb +13 -1
  32. data/lib/picsolve_docker_builder/helpers/config/base.rb +14 -0
  33. data/lib/picsolve_docker_builder/helpers/config/secret.rb +14 -0
  34. data/lib/picsolve_docker_builder/helpers/config/variable_object.rb +68 -0
  35. data/lib/picsolve_docker_builder/helpers/config_manager.rb +96 -0
  36. data/lib/picsolve_docker_builder/helpers/kubernetes/rc.rb +28 -6
  37. data/lib/picsolve_docker_builder/helpers/kubernetes_manager.rb +126 -47
  38. data/lib/picsolve_docker_builder/helpers/repository.rb +89 -3
  39. data/lib/picsolve_docker_builder/helpers/ssh_forward.rb +9 -1
  40. data/lib/picsolve_docker_builder/nodejs.rb +135 -0
  41. data/lib/picsolve_docker_builder/version.rb +1 -1
  42. data/lib/tasks/compose.rake +2 -0
  43. data/lib/tasks/nodejs.rake +11 -0
  44. data/picsolve_docker_builder.gemspec +1 -1
  45. metadata +36 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 15bcfea24b318c9f934f15dcfdd65d5ed4be8d99
4
- data.tar.gz: cb6e0b70bc6ca5ff68ebb873a73266bfe763c441
3
+ metadata.gz: 47c0bcbcd965d2446b0c1c9254a67bbd23a9569d
4
+ data.tar.gz: 1a4f008a15c22534b990a77bca137fb4b04c0464
5
5
  SHA512:
6
- metadata.gz: 55b9b50d6c5409344b7fa6e6c40e06ad9f4c7904ee2e30c9c47b0b6456f522e5ac274fc24b510edb5e89f4e6d4d24bac274d39e247d428d81fdf40b83df6268b
7
- data.tar.gz: 5b306bfde7d4bd052037da1e16c8de9a9c27c7acfa917bace4838f72ab8fa5a74fe162d93feadb9177cd2f006ce0974aef586f96f859100c56c60004b6a75f80
6
+ metadata.gz: 34289ce6a0dfea6cb6ac0b4bf23f76bad8a7300b91e3c75dbb5d63ece96f17d61e5dd9dd08d0997cf668948e98d5bf4728065c9915f8714c6ac0fe1dae473836
7
+ data.tar.gz: d042eaacd90ded220dd645d5763dccc4cc0ff37e5bdd1c25f742ead7f1ed2483ab44f0d33cc6eff9ecd6d5573834979cd76554054e61452b656ca8819bf3be13
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Change Log
2
2
 
3
+ ## [0.2.0] - 2015-08-26
4
+ ### Added
5
+ - Upgrade kubernetes api to v1
6
+ - Create integration tests for most used cases
7
+ - Implement cleanup of orphaned pods (fixes DE128)
8
+ - Implement alpha support of new config file for composing (support of env vars per stage)
9
+
3
10
  ## [0.1.1] - 2015-07-03
4
11
  ### Fixed
5
12
  - Flush buffers for better jenkins experience
data/README.md CHANGED
@@ -3,9 +3,52 @@
3
3
  ## Example config file `.docker-builder.yml`
4
4
 
5
5
  ```yaml
6
+ ---
7
+ compose:
8
+ app_name: hello_world
9
+ clusters:
10
+ - dev-1b.kubernetes.picsolve.net
11
+ - dev-1c.kubernetes.picsolve.net
12
+ containers:
13
+ container1:
14
+ image: docker.picsolve.net/image1
15
+ environment:
16
+ default:
17
+ - COOL=${variable:cool}
18
+ - TERM=xterm
19
+ - "DB_USER=#{variable:db_username}"
20
+ - "DB_PASSWORD=#{secret:database:password}"
21
+ - "DB_NAME=#{stage}-#{app_name}"
22
+ qa:
23
+ - ENABLE_QA=1
24
+ ci:
25
+ - ENABLE_CI=1
26
+ ports:
27
+ - container_port: 9000
28
+ service_port: 9000
29
+ requirements:
30
+ bucket:
31
+ type: s3bucket
32
+ database:
33
+ type: postgres
34
+ variables:
35
+ default:
36
+ cool: yes
37
+ db_username: dbuser_default
38
+ ci:
39
+ db_username: dbuser_ci
40
+ qa:
41
+ db_username: dbuser_qa
6
42
  docker:
7
43
  base_image: base-image-name
8
44
  image_name: dest-image-name
45
+ build_environment:
46
+ - TERM=xterm
47
+ build_requirements:
48
+ bucket:
49
+ type: s3bucket
50
+ database:
51
+ type: postgres
9
52
  dockerfile_hooks:
10
53
  asset_build:
11
54
  early: |
@@ -20,8 +63,8 @@ docker:
20
63
  scala:
21
64
  sbt:
22
65
  build_task:
23
- - clean
24
- - universal:packageZipTarball
66
+ - clean
67
+ - "universal:packageZipTarball"
25
68
  ```
26
69
 
27
70
  ## Release process
@@ -0,0 +1,18 @@
1
+ compose:
2
+ app_name: hello_world_test_new
3
+ clusters:
4
+ - dev-1b.kubernetes.picsolve.net
5
+ containers:
6
+ helloworld:
7
+ image: docker.picsolve.net/hello-world
8
+ environment:
9
+ default:
10
+ - DEFAULT=true
11
+ - ENV=default
12
+ qa:
13
+ - ENV=qa
14
+ ci:
15
+ - ENV=ci
16
+ ports:
17
+ - container_port: 80
18
+ service_port: 80
@@ -0,0 +1 @@
1
+ Gemfile.lock
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gem 'picsolve_docker_builder', path: '../../'
@@ -0,0 +1,3 @@
1
+ # Load upstream tasks
2
+ spec = Gem::Specification.find_by_name 'picsolve_docker_builder'
3
+ load "#{spec.gem_dir}/lib/tasks/compose.rake"
@@ -0,0 +1,4 @@
1
+ compose:
2
+ app_name: hello_world_test
3
+ clusters:
4
+ - dev-1b.kubernetes.picsolve.net
@@ -0,0 +1 @@
1
+ Gemfile.lock
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gem 'picsolve_docker_builder', path: '../../'
@@ -0,0 +1,3 @@
1
+ # Load upstream tasks
2
+ spec = Gem::Specification.find_by_name 'picsolve_docker_builder'
3
+ load "#{spec.gem_dir}/lib/tasks/compose.rake"
@@ -0,0 +1,4 @@
1
+ helloworld:
2
+ image: docker.picsolve.net/hello-world
3
+ ports:
4
+ - 80:80
@@ -0,0 +1,25 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe 'Integration tests' do
4
+ before(:each) do
5
+ docker_needed!
6
+ end
7
+ describe 'compose:deploy' do
8
+ describe 'hello world image (old config)' do
9
+ let :path do
10
+ 'integration/compose_hello_world_old_config'
11
+ end
12
+ it 'runs successfully' do
13
+ bundle_exec 'compose:deploy'
14
+ end
15
+ end
16
+ describe 'hello world image (new config)' do
17
+ let :path do
18
+ 'integration/compose_hello_world_new_config'
19
+ end
20
+ it 'runs successfully' do
21
+ bundle_exec 'compose:deploy'
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,45 @@
1
+ require 'docker'
2
+ require 'open3'
3
+
4
+ # Helpers for integration tests
5
+ module IntegrationHelpers
6
+ def sh(command)
7
+ env = {
8
+ 'PATH' => ENV['PATH'],
9
+ 'GEM_PATH' => ENV['GEM_PATH'],
10
+ 'HOME' => ENV['HOME'],
11
+ 'SSH_AUTH_SOCK' => ENV['SSH_AUTH_SOCK']
12
+ }
13
+ Open3.popen3(
14
+ env,
15
+ command,
16
+ unsetenv_others: true
17
+ ) do |stdin, stdout, stderr, wait_thr|
18
+ stdin.close
19
+ stdout.each_line do |line|
20
+ $stdout.write(line)
21
+ $stdout.flush
22
+ end
23
+ stderr.each_line do |line|
24
+ $stderr.write(line)
25
+ $stderr.flush
26
+ end
27
+ exit_status = wait_thr.value
28
+ fail 'Exit code is not zero' if exit_status != 0
29
+ end
30
+ end
31
+
32
+ def bundle_exec(task)
33
+ Dir.chdir(path) do
34
+ sh 'rm -f Gemfile.lock'
35
+ sh 'bundle install'
36
+ sh "bundle exec rake #{task}"
37
+ end
38
+ end
39
+
40
+ def docker_needed!
41
+ Docker.info.inspect
42
+ rescue Excon::Errors::Error
43
+ skip 'No docker daemon available'
44
+ end
45
+ end
@@ -1,50 +1,16 @@
1
- require 'picsolve_docker_builder/helpers/repository'
2
- require 'docker'
3
- require 'open3'
4
-
5
- def sh(command)
6
- env = {
7
- 'PATH' => ENV['PATH'],
8
- 'GEM_PATH' => ENV['GEM_PATH']
9
- }
10
- Open3.popen3(
11
- env,
12
- command,
13
- unsetenv_others: true
14
- ) do |stdin, stdout, stderr, wait_thr|
15
- stdin.close
16
- stdout.each_line do |line|
17
- $stdout.write(line)
18
- $stdout.flush
19
- end
20
- stderr.each_line do |line|
21
- $stderr.write(line)
22
- $stderr.flush
23
- end
24
- exit_status = wait_thr.value
25
- fail 'Exit code is not zero' if exit_status != 0
26
- end
27
- end
1
+ require_relative 'spec_helper'
28
2
 
29
3
  describe 'Integration tests' do
30
4
  before(:each) do
31
- begin
32
- Docker.info.inspect
33
- rescue Excon::Errors::Error
34
- skip 'No docker daemon available'
35
- end
5
+ docker_needed!
36
6
  end
37
7
  describe 'docker build' do
38
- describe 'play hello world' do
8
+ describe 'play app hello world' do
39
9
  let :path do
40
10
  'integration/play_hello_world'
41
11
  end
42
12
  it 'builds successfully' do
43
- Dir.chdir(path) do
44
- sh 'rm -f Gemfile.lock'
45
- sh 'bundle install'
46
- sh 'bundle exec rake docker:build'
47
- end
13
+ bundle_exec 'docker:build'
48
14
  end
49
15
  end
50
16
  end
@@ -0,0 +1,12 @@
1
+ logs
2
+ /.ivy2
3
+ /.m2
4
+ /.sbt
5
+ target
6
+ /.idea
7
+ /.idea_modules
8
+ /.classpath
9
+ /.project
10
+ /.settings
11
+ /RUNNING_PID
12
+ Gemfile.lock
@@ -0,0 +1,4 @@
1
+ This is your new library module
2
+ =================================
3
+
4
+ This file will be packaged with your application, when using `activator dist`.
@@ -0,0 +1,8 @@
1
+ package picsolve.helloworld
2
+
3
+ import java.util.Date
4
+
5
+ /**
6
+ * Created by nicolas on 17/07/15.
7
+ */
8
+ case class Person(name: String, birthDay: Date)
@@ -0,0 +1,42 @@
1
+ releaseSettings
2
+
3
+ organization := "picsolve"
4
+
5
+ val artifactId = "lib.hello_world"
6
+
7
+ name := artifactId
8
+
9
+ moduleName := artifactId
10
+
11
+ lazy val root = (project in file(".")).enablePlugins(PlayScala)
12
+
13
+ scalaVersion := "2.11.6"
14
+
15
+ lazy val picsolveArtifactoryRepository = "http://artifactory.dev.services.picsolve.net:8081/artifactory"
16
+
17
+ lazy val picsolveResolvers = Seq (
18
+ "Picsolve releases repository" at s"$picsolveArtifactoryRepository/libs-release/",
19
+ "Picsolve snapshots repository" at s"$picsolveArtifactoryRepository/libs-snapshot/"
20
+ )
21
+
22
+ resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
23
+
24
+ resolvers ++= picsolveResolvers
25
+
26
+ resolvers += "scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"
27
+
28
+
29
+ libraryDependencies ++= Seq(
30
+ specs2 % Test,
31
+ "com.typesafe.scala-logging" %% "scala-logging" % "3.1.0"
32
+ )
33
+
34
+
35
+ publishTo <<= version {
36
+ (v: String) =>
37
+ val repo = "http://artifactory.dev.services.picsolve.net:8081/artifactory/"
38
+ if (v.trim.endsWith("SNAPSHOT"))
39
+ Some("snapshots" at repo + "libs-snapshot-local")
40
+ else
41
+ Some("releases" at repo + "libs-release-local")
42
+ }
File without changes
@@ -0,0 +1,22 @@
1
+ <configuration>
2
+
3
+ <conversionRule conversionWord="coloredLevel" converterClass="play.api.Logger$ColoredLevel" />
4
+
5
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
6
+ <encoder>
7
+ <pattern>%coloredLevel - %logger - %message%n%xException</pattern>
8
+ </encoder>
9
+ </appender>
10
+
11
+ <!--
12
+ The logger name is typically the Java/Scala package name.
13
+ This configures the log level to log at for a package and its children packages.
14
+ -->
15
+ <logger name="play" level="INFO" />
16
+ <logger name="application" level="DEBUG" />
17
+
18
+ <root level="ERROR">
19
+ <appender-ref ref="STDOUT" />
20
+ </root>
21
+
22
+ </configuration>
@@ -0,0 +1,4 @@
1
+ #Activator-generated Properties
2
+ #Mon Jun 29 12:18:44 BST 2015
3
+ template.uuid=49a31253-85ed-4c4f-9041-f2f030591a8d
4
+ sbt.version=0.13.8
@@ -0,0 +1,4 @@
1
+ // The Play plugin
2
+ addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.4.0")
3
+
4
+ addSbtPlugin("com.github.gseitz" %% "sbt-release" % "0.8.4")
@@ -0,0 +1,24 @@
1
+ import java.util.Date
2
+
3
+ import org.junit.runner._
4
+ import org.specs2.mutable._
5
+ import org.specs2.runner._
6
+ import picsolve.helloworld.Person
7
+ import play.api.test._
8
+
9
+ @RunWith(classOf[JUnitRunner])
10
+ class PersonSpec extends Specification {
11
+
12
+ "Person" should {
13
+
14
+ "return their name correclty" in new WithApplication{
15
+ val name = "A Name"
16
+ Person(name,new Date()).name === name
17
+ }
18
+
19
+ "return their birthDay correclty" in new WithApplication{
20
+ val birthDay = new Date()
21
+ Person("A Name",birthDay).birthDay === birthDay
22
+ }
23
+ }
24
+ }
@@ -0,0 +1 @@
1
+ version in ThisBuild := "0.0.1-SNAPSHOT"
@@ -1,3 +1,5 @@
1
+ require_relative 'integration_helpers'
1
2
  RSpec.configure do |config|
3
+ config.include IntegrationHelpers
2
4
  config.mock_with :rspec
3
5
  end
@@ -21,6 +21,7 @@ module PicsolveDockerBuilder
21
21
  end
22
22
 
23
23
  def ports
24
+ return if @opts[:ports].nil?
24
25
  ports = @opts[:ports]
25
26
  ports = [ports] unless ports.is_a?(Array)
26
27
  ports.map do |port|
@@ -37,7 +38,8 @@ module PicsolveDockerBuilder
37
38
  end
38
39
 
39
40
  def command
40
- "[\"#{@opts[:command].join('", "')}\"]"
41
+ return '' if @opts[:command].nil?
42
+ "CMD [\"#{@opts[:command].join('", "')}\"]"
41
43
  end
42
44
 
43
45
  def hook(name)
@@ -103,7 +105,7 @@ MAINTAINER #{maintainer}
103
105
  #{ports}
104
106
 
105
107
  # call run script
106
- CMD #{command}
108
+ #{command}
107
109
 
108
110
  #{hook(:late)}
109
111
  EOS
@@ -1,5 +1,6 @@
1
1
  require 'picsolve_docker_builder/base'
2
2
  require 'picsolve_docker_builder/helpers/kubernetes_manager'
3
+ require 'picsolve_docker_builder/helpers/config_manager'
3
4
  require 'picsolve_docker_builder/composer/image'
4
5
  require 'excon'
5
6
  require 'psych'
@@ -24,72 +25,6 @@ module PicsolveDockerBuilder
24
25
  @stage = my_stage.downcase
25
26
  end
26
27
 
27
- def deploy_services
28
- images.each do |i|
29
- i.service.deploy
30
- end
31
- end
32
-
33
- def deploy_rcs
34
- images.each do |i|
35
- i.rc.deploy
36
- end
37
- end
38
-
39
- def wait_for_deployed_rcs
40
- wait_timeout = 300
41
- wait_sleep = 2
42
- wait_beginning = 15
43
- wait_count = wait_beginning
44
- unready_images = images.dup
45
- log.info \
46
- 'Wait for the new pods to be up and running for at least 20 seconds'
47
- sleep wait_beginning
48
- loop do
49
- unready_images.each do |i|
50
- unready_images.delete(i) if i.rc.ready?
51
- end
52
- log.debug "Still waiting for: #{unready_images.map(&:name)}"
53
- $stdout.flush
54
- $stderr.flush
55
- wait_count += wait_sleep
56
- break if wait_count > wait_timeout
57
- break if unready_images.length == 0
58
- sleep wait_sleep
59
- end
60
- successful_images = images.dup
61
- unready_images.each do |u|
62
- successful_images.delete(u)
63
- end
64
- [successful_images, unready_images]
65
- end
66
-
67
- def remove_old_rcs(successful_images)
68
- # build list of successful deplyoed images
69
- successful_images.each do |i|
70
- log.debug "Remove pods for #{i.name}"
71
- i.rc.remove_old_rcs
72
- end
73
- end
74
-
75
- def deploy
76
- log.info "start deploying app_name=#{app_name} to stage #{stage}"
77
-
78
- # reset hash
79
- @hash = nil
80
-
81
- deploy_services
82
-
83
- deploy_rcs
84
-
85
- successful_images, unready_images = wait_for_deployed_rcs
86
-
87
- remove_old_rcs(successful_images)
88
-
89
- fail "Failed to deploy this service: #{unready_images.map(&:name)}" \
90
- if unready_images.length > 0
91
- end
92
-
93
28
  def app_name
94
29
  config['compose']['app_name'].downcase.gsub(/[^a-z0-9\-]/, '-')
95
30
  end
@@ -98,10 +33,6 @@ module PicsolveDockerBuilder
98
33
  "#{app_name}-#{stage}".downcase
99
34
  end
100
35
 
101
- def kubernetes
102
- @kubernetes ||= PicsolveDockerBuilder::Helpers::KubernetesManager.new
103
- end
104
-
105
36
  def hash
106
37
  @hash ||= SecureRandom.hex[0..7]
107
38
  end
@@ -114,12 +45,51 @@ module PicsolveDockerBuilder
114
45
  @images ||= read_images
115
46
  end
116
47
 
48
+ def kubernetes_clusters
49
+ config['compose']['clusters'].map do |cluster|
50
+ PicsolveDockerBuilder::Helpers::KubernetesManager.new(
51
+ self,
52
+ cluster,
53
+ :ssh_forward, # TODO: support other types here
54
+ )
55
+ end
56
+ end
57
+
58
+ def deploy
59
+ errors = 0
60
+ kubernetes_clusters.each do |cluster|
61
+ begin
62
+ log.info "Deploy to kubernetes cluster #{cluster.host}"
63
+ cluster.deploy
64
+ cluster.stop
65
+ rescue StandardError => e
66
+ errors += 1
67
+ log.error "Failed deployment to kubernetes cluster: #{e}"
68
+ e.backtrace.each do |line|
69
+ log.error line
70
+ end
71
+ end
72
+ end
73
+ fail 'deployment to at least one cluster failed' if errors > 0
74
+ end
75
+
117
76
  def read_images
118
- i = []
119
- docker_compose.each do |name, config|
120
- i << Image.new(name, config, self)
77
+ # classic config
78
+ containers = docker_compose
79
+ unless containers.nil?
80
+ i = []
81
+ containers.each do |name, config|
82
+ i << Image.new(name, config, self)
83
+ end
84
+ return i
121
85
  end
122
- i
86
+
87
+ # new approach
88
+ c = PicsolveDockerBuilder::Helpers::ConfigManager.new(
89
+ config_path,
90
+ stage
91
+ )
92
+ c.containers(self)
123
93
  end
124
94
 
125
95
  def docker_compose
@@ -139,6 +109,7 @@ module PicsolveDockerBuilder
139
109
  Psych.load_file path
140
110
  rescue Errno::ENOENT
141
111
  log.debug "can not find docker-compose.yml at '#{path}'"
112
+ nil
142
113
  end
143
114
 
144
115
  def query_registry
@@ -0,0 +1,79 @@
1
+ require 'picsolve_docker_builder/base'
2
+ require 'picsolve_docker_builder/composer/registry'
3
+
4
+ module PicsolveDockerBuilder
5
+ module Composer
6
+ # Represents an container in an namespace
7
+ class Container
8
+ include PicsolveDockerBuilder::Base
9
+ attr_reader :config, :name, :composer
10
+ def initialize(name, config, composer)
11
+ log.info "Image name=#{name} config=#{config}"
12
+ @config = config
13
+ @name = name
14
+ @composer = composer
15
+ log.info "repo_tag_uniqe is #{repo_tag_unique}"
16
+ end
17
+
18
+ def repo_tag
19
+ config['image']
20
+ end
21
+
22
+ def rc(kubernetes)
23
+ @rcs = {} if @rcs.nil?
24
+ @rcs[kubernetes] = kubernetes.rc(self) \
25
+ unless @rcs.key?(kubernetes)
26
+ @rcs[kubernetes]
27
+ end
28
+
29
+ def service(kubernetes)
30
+ @services = {} if @rcs.nil?
31
+ @services[kubernetes] = kubernetes.service(self) \
32
+ unless @services.key?(kubernetes)
33
+ @services[kubernetes]
34
+ end
35
+
36
+ def environment
37
+ return nil unless config.key? 'environment'
38
+ config['environment'].map do |key, value|
39
+ {
40
+ 'name' => key,
41
+ 'value' => value
42
+ }
43
+ end
44
+ end
45
+
46
+ def ports
47
+ config['ports'].map do |port|
48
+ {
49
+ 'port' => port['container_port'].to_i
50
+ }
51
+ end
52
+ rescue StandardError
53
+ []
54
+ end
55
+
56
+ def ports_rc
57
+ p = []
58
+ ports.each do |port|
59
+ p << {
60
+ 'containerPort' => port['port']
61
+ }
62
+ end
63
+ p
64
+ end
65
+
66
+ def repo_tag_hash_unique
67
+ @repo_tag_hash_unique ||= Registry.repo_tag_unique(config['image'])
68
+ end
69
+
70
+ def repo_tag_unique
71
+ repo_tag_hash_unique[:tag_unique]
72
+ end
73
+
74
+ def hash
75
+ repo_tag_hash_unique[:hash]
76
+ end
77
+ end
78
+ end
79
+ end