altaire-siren 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -2
  3. data/Gemfile +0 -1
  4. data/Gemfile.lock +7 -1
  5. data/altaire-siren.gemspec +1 -0
  6. data/build-schema.rb +206 -0
  7. data/docs/docs/commands/song.md +3 -0
  8. data/fantasia-export.rb +16 -0
  9. data/lib/siren.rb +2 -0
  10. data/lib/siren/cli.rb +16 -1
  11. data/lib/siren/compose.rb +103 -0
  12. data/lib/siren/compose/service.rb +321 -0
  13. data/lib/siren/compose/types.rb +230 -0
  14. data/lib/siren/schemabuilder.rb +56 -0
  15. data/lib/siren/song.rb +78 -50
  16. data/lib/siren/stack.rb +6 -2
  17. data/lib/siren/version.rb +1 -1
  18. data/schemas/docker-compose.yaml +78 -0
  19. metadata +23 -47
  20. data/docs/site/404.html +0 -313
  21. data/docs/site/assets/fonts/font-awesome.css +0 -4
  22. data/docs/site/assets/fonts/material-icons.css +0 -13
  23. data/docs/site/assets/fonts/specimen/FontAwesome.ttf +0 -0
  24. data/docs/site/assets/fonts/specimen/FontAwesome.woff +0 -0
  25. data/docs/site/assets/fonts/specimen/FontAwesome.woff2 +0 -0
  26. data/docs/site/assets/fonts/specimen/MaterialIcons-Regular.ttf +0 -0
  27. data/docs/site/assets/fonts/specimen/MaterialIcons-Regular.woff +0 -0
  28. data/docs/site/assets/fonts/specimen/MaterialIcons-Regular.woff2 +0 -0
  29. data/docs/site/assets/images/favicon.png +0 -0
  30. data/docs/site/assets/images/icons/bitbucket.1b09e088.svg +0 -1
  31. data/docs/site/assets/images/icons/github.f0b8504a.svg +0 -1
  32. data/docs/site/assets/images/icons/gitlab.6dd19c00.svg +0 -1
  33. data/docs/site/assets/javascripts/application.c648116f.js +0 -6
  34. data/docs/site/assets/javascripts/lunr/lunr.da.js +0 -1
  35. data/docs/site/assets/javascripts/lunr/lunr.de.js +0 -1
  36. data/docs/site/assets/javascripts/lunr/lunr.du.js +0 -1
  37. data/docs/site/assets/javascripts/lunr/lunr.es.js +0 -1
  38. data/docs/site/assets/javascripts/lunr/lunr.fi.js +0 -1
  39. data/docs/site/assets/javascripts/lunr/lunr.fr.js +0 -1
  40. data/docs/site/assets/javascripts/lunr/lunr.hu.js +0 -1
  41. data/docs/site/assets/javascripts/lunr/lunr.it.js +0 -1
  42. data/docs/site/assets/javascripts/lunr/lunr.ja.js +0 -1
  43. data/docs/site/assets/javascripts/lunr/lunr.jp.js +0 -1
  44. data/docs/site/assets/javascripts/lunr/lunr.multi.js +0 -1
  45. data/docs/site/assets/javascripts/lunr/lunr.nl.js +0 -1
  46. data/docs/site/assets/javascripts/lunr/lunr.no.js +0 -1
  47. data/docs/site/assets/javascripts/lunr/lunr.pt.js +0 -1
  48. data/docs/site/assets/javascripts/lunr/lunr.ro.js +0 -1
  49. data/docs/site/assets/javascripts/lunr/lunr.ru.js +0 -1
  50. data/docs/site/assets/javascripts/lunr/lunr.stemmer.support.js +0 -1
  51. data/docs/site/assets/javascripts/lunr/lunr.sv.js +0 -1
  52. data/docs/site/assets/javascripts/lunr/lunr.th.js +0 -1
  53. data/docs/site/assets/javascripts/lunr/lunr.tr.js +0 -1
  54. data/docs/site/assets/javascripts/lunr/tinyseg.js +0 -1
  55. data/docs/site/assets/javascripts/lunr/wordcut.js +0 -1
  56. data/docs/site/assets/javascripts/modernizr.74668098.js +0 -1
  57. data/docs/site/assets/stylesheets/application-palette.a8b3c06d.css +0 -1
  58. data/docs/site/assets/stylesheets/application.30686662.css +0 -1
  59. data/docs/site/commands/crypto/index.html +0 -470
  60. data/docs/site/commands/song/index.html +0 -474
  61. data/docs/site/index.html +0 -348
  62. data/docs/site/search/search_index.json +0 -1
  63. data/docs/site/sitemap.xml +0 -18
  64. data/docs/site/sitemap.xml.gz +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c2c8b0c8610868e3400d37267b62e46e46a8151cc9bfc71ec606d2de5b5c9b4
4
- data.tar.gz: a40f94a53642d50b7e07e956fd785d796826ad4107fb653ddadc439e99aa09b9
3
+ metadata.gz: b643929d013ecfea84037c6606ca2e9b99c06b393bf9c1a1a666d9c41ad3bb2b
4
+ data.tar.gz: 7430a99fb970c6a786ebbad3854823454da1e8502d70272abf91a5dc0d752a07
5
5
  SHA512:
6
- metadata.gz: '086793744a02fba270cf0441ac85cc406383898d9c1488b07129a15eedbb551b80d8fb142da7ab5beb31f8a57be1118ca0b4d80be30aba7c912a87d62aaaa53d'
7
- data.tar.gz: de3aaea9db9eb23c1a26257f49cea1ec0638a8c2e0b6f15fa67311046083df194826f7a953cbdd3a6244db2cdb20444ab7a56600eb3c32c98ca881370c8ee5ce
6
+ metadata.gz: d6f64e1a3bb9d88ec27362b18e0ec7b62bc7c344ae2597abe5922c961d12fbc8fb6af143b91bc808b77286d2eadbef0de5982179a204deecbb03b20d8ce1f3e7
7
+ data.tar.gz: 414dd254d30288e6bc9d1e810b49a5e75522cdd548fbd8b422e1ce7e2937452955e7e00aa40262ffd084d537a73f8c03a0f789b331d1c7c6090dca6f74563f4a
data/.gitignore CHANGED
@@ -6,5 +6,5 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
- /data/songs/*.yaml
10
- /private.jwk
9
+ /data/
10
+ /private.jwk
data/Gemfile CHANGED
@@ -1,4 +1,3 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in stack.gemspec
4
3
  gemspec
data/Gemfile.lock CHANGED
@@ -1,13 +1,16 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- altaire-siren (0.1.0)
4
+ altaire-siren (0.1.1)
5
5
  clamp (= 1.3.1)
6
6
  jose (= 1.1.3)
7
+ json-schema (= 2.8.1)
7
8
 
8
9
  GEM
9
10
  remote: https://rubygems.org/
10
11
  specs:
12
+ addressable (2.7.0)
13
+ public_suffix (>= 2.0.2, < 5.0)
11
14
  aruba (0.14.12)
12
15
  childprocess (>= 0.6.3, < 4.0.0)
13
16
  contracts (~> 0.9)
@@ -44,8 +47,11 @@ GEM
44
47
  concurrent-ruby (~> 1.0)
45
48
  jose (1.1.3)
46
49
  hamster
50
+ json-schema (2.8.1)
51
+ addressable (>= 2.4)
47
52
  multi_json (1.14.1)
48
53
  multi_test (0.1.2)
54
+ public_suffix (4.0.1)
49
55
  rake (10.5.0)
50
56
  rspec (3.9.0)
51
57
  rspec-core (~> 3.9.0)
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  spec.add_dependency "jose", "1.1.3"
25
25
  spec.add_dependency "clamp", "1.3.1"
26
+ spec.add_dependency "json-schema", "2.8.1"
26
27
 
27
28
  spec.add_development_dependency "bundler", "~> 2.0"
28
29
  spec.add_development_dependency "rake", "~> 10.0"
data/build-schema.rb ADDED
@@ -0,0 +1,206 @@
1
+ require 'siren/schemabuilder'
2
+ require 'json'
3
+ require 'yaml'
4
+
5
+ Siren::JSONSchema::SchemaBuilder.new do
6
+
7
+ def hashlike
8
+ any(array(string), hash(string))
9
+ end
10
+
11
+ def resources
12
+ object(cpus: string, memory: string)
13
+ end
14
+
15
+ def duration
16
+ string(/^(\d+h)?(\d+m)?(\d+s)?(\d+ms)?(\d+us)?$/)
17
+ end
18
+
19
+ def bytesize
20
+ string(/^(\d+)(b|k|m|g|kb|mb|gb)?$/)
21
+ end
22
+
23
+ def build
24
+ o = object(
25
+ version: string,
26
+ services: hash(object(
27
+ image: string,
28
+ build: string,
29
+ ports: array(string),
30
+ volumes: array(string),
31
+ environment: hashlike,
32
+ deploy: object(
33
+ replicas: integer,
34
+ ),
35
+ command: any(string, array(string)),
36
+ )),
37
+ "x-domains": array(object(
38
+ name: string,
39
+ path: string,
40
+ service: string,
41
+ port: string,
42
+ auth: string,
43
+ )),
44
+ "x-ports": array(object(
45
+ service: string,
46
+ inside: string,
47
+ outside: string,
48
+ protocol: string,
49
+ )),
50
+ "x-env": hash(string),
51
+ # services: hash(
52
+ # build: any(string, object(
53
+ # context: string,
54
+ # dockerfile: string,
55
+ # args: hashlike,
56
+ # cache_from: array(string),
57
+ # labels: hashlike,
58
+ # shm_size: string,
59
+ # target: string)
60
+ # ),
61
+ # command: any(string, array(string)),
62
+ # configs: array(any(string, object(
63
+ # source: string, target: string, uid: any(string, integer), gid: any(string, integer), mode: any(string, integer)
64
+ # ))),
65
+ # container_name: string,
66
+ # credential_spec: any(object(file: string), object(registry: string), object(config: string)),
67
+ # deploy: object(
68
+ # endpoint_mode: string(["vip", "dnsrr"]),
69
+ # labels: hashlike,
70
+ # mode: string(["global", "replicated"]),
71
+ # placement: object(
72
+ # constraints: array(string),
73
+ # preferences: array(object(spread: string)),
74
+ # ),
75
+ # replicas: integer,
76
+ # resources: object(
77
+ # limits: resources,
78
+ # reservations: resources,
79
+ # ),
80
+ # restart_policy: object(
81
+ # condition: string(["none", "on-failure", "any"]),
82
+ # delay: duration,
83
+ # max_attemtps: integer,
84
+ # window: duration,
85
+ # ),
86
+ # rollback_config: object(
87
+ # parallelism: integer,
88
+ # delay: duration,
89
+ # failure_action: string(["continue", "pause"]),
90
+ # monitor: duration,
91
+ # max_failure_ratio: number,
92
+ # order: string(["stop-first", "start-first"]),
93
+ # ),
94
+ # update_config: object(
95
+ # parallelism: integer,
96
+ # delay: duration,
97
+ # failure_action: string(["continue", "pause", "rollback"]),
98
+ # monitor: duration,
99
+ # max_failure_ratio: number,
100
+ # order: string(["stop-first", "start-first"]),
101
+ # ),
102
+ # ),
103
+ # dns: any(string, array(string)),
104
+ # dns_search: any(string, array(string)),
105
+ # entrypoint: any(string, array(string)),
106
+ # environment: hashlike,
107
+ # expose: array(string),
108
+ # extra_hosts: array(string),
109
+ # healthcheck: object(
110
+ # test: any(string, array(string)),
111
+ # interval: duration,
112
+ # timeout: duration,
113
+ # retries: integer,
114
+ # start_period: duration,
115
+ # ),
116
+ # image: string,
117
+ # init: bool,
118
+ # labels: hashlike,
119
+ # logging: object(
120
+ # driver: string,
121
+ # options: hash(string),
122
+ # ),
123
+ # networks: any(array(string), hash(object(aliases: array(string), ipv4_address: string, ipv6_address: string))),
124
+ # pid: string("host"),
125
+ # ports: array(any(string, object(target: integer, published: integer, protocol: string(["tcp", "udp"]), mode: string(["host", "ingress"])))),
126
+ # secrets: array(any(string, object(source: string, target: string, uid: integer, gid: integer, mode: integer))),
127
+ # stop_grace_period: duration,
128
+ # stop_signal: string(/^SIG/),
129
+ # sysctls: hashlike,
130
+ # ulimits: hash(any(integer, object(soft: integer, hard: integer))),
131
+ # volumes: array(any(string,
132
+ # object(type: string(["volume", "bind", "tmpfs", "npipe"]),
133
+ # source: string, target: string, read_only: boolean,
134
+ # consistency: string(["consistent", "cached", "delegated"]),
135
+ # volume: object(nocopy: boolean), bind: object(propagation: string),
136
+ # tmpfs: object(size: bytesize)),
137
+ # )),
138
+ # domainname: string,
139
+ # hostname: string,
140
+ # ipc: string,
141
+ # mac_address: string,
142
+ # privileged: boolean,
143
+ # read_only: boolean,
144
+ # shm_size: bytesize,
145
+ # stdin_open: boolean,
146
+ # tty: boolean,
147
+ # user: any(string, integer),
148
+ # working_dir: string,
149
+ # ),
150
+ # volumes: hash(any(null, object(driver: string, driver_opts: hash(string), external: boolean, labels: hashlike, name: string))),
151
+ # networks: hash(any(null, object(
152
+ # driver: string,
153
+ # driver_opts: hash(string),
154
+ # external: any(boolean, object(name: string)),
155
+ # attachable: boolean,
156
+ # ipam: object(
157
+ # driver: string,
158
+ # config: array(object(subnet: string))
159
+ # ),
160
+ # internal: boolean,
161
+ # labels: hashlike,
162
+ # name: string,
163
+ # ))),
164
+ # configs: hash(object(file: string, external: any(boolean, object(name: string)))),
165
+ # secrets: hash(object(file: string, external: boolean, name: string)),
166
+ )
167
+ # o.delete(:additionalProperties)
168
+ # o[:patternProperties] = {"^x-" => {}}
169
+ o
170
+ end
171
+
172
+ end
173
+
174
+ # cap_add: *string-array
175
+ # cap_drop: *string-array
176
+ # cgroup_parent: *string
177
+ # command: *string-or-array
178
+ # configs:
179
+ # type: array
180
+ # items:
181
+ # anyOf:
182
+ # - type: string
183
+ # - type: object
184
+ # additionalProperties: false
185
+ # properties:
186
+ # source: *string
187
+ # target: *string
188
+ # uid: *string-or-number
189
+ # gid: *string-or-number
190
+ # mode: *string-or-number
191
+ # volumes:
192
+ # type: array
193
+ # items:
194
+ # type: string
195
+ # ports:
196
+ # type: array
197
+ # items:
198
+ # anyOf:
199
+ # - type: string
200
+ # - type: object
201
+ # additionalProperties: false
202
+ # properties:
203
+ # context: *string
204
+ # dockerfile: *string
205
+ # args: *string-array
206
+ # environment: *key-values
@@ -51,6 +51,9 @@ spec:
51
51
  publish:
52
52
  - # The port the service is listening on.
53
53
  port: 8081
54
+ # Expose this port on a dedicated load balancer.
55
+ # If unset, expose the port via Traefik.
56
+ loadBalancer: lb-name
54
57
  # Domain name to use.
55
58
  domain: builder.k9.altaire.xyz
56
59
  # Use built-in Altaire auth.
@@ -0,0 +1,16 @@
1
+ require 'pg'
2
+ require 'yaml'
3
+
4
+ db = PG::Connection.open(host: "db.altaire.com", user: "postgres", dbname: "fantasia")
5
+
6
+ db.exec("SELECT name, composefile, fantasiafile, envfile, tags FROM stacks WHERE archived_at IS NULL").each do |row|
7
+ name, compose, fantasia, env, tags = row.values
8
+ compose = YAML.load(compose)
9
+ fantasia = YAML.load(fantasia)
10
+ File.open("data/stacks/#{name}.yml", "w") do |file|
11
+ compose["x-domains"] = fantasia["domains"]
12
+ compose["x-ports"] = fantasia["ports"]
13
+ compose["x-env"] = env.split("\n").map{|l|l.split("=", 2)}.to_h
14
+ file.puts compose.to_yaml
15
+ end
16
+ end
data/lib/siren.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  require "siren/version"
2
2
  require "siren/crypto"
3
3
  require "siren/song"
4
+ require "siren/compose"
4
5
  require "siren/stack"
5
6
 
6
7
  module Siren
8
+ ROOT = File.join(__dir__, "..")
7
9
  class Error < StandardError; end
8
10
  # Your code goes here...
9
11
  end
data/lib/siren/cli.rb CHANGED
@@ -5,6 +5,20 @@ require 'siren'
5
5
  module Siren
6
6
  module CLI
7
7
 
8
+ class ComposeCommand < Clamp::Command
9
+
10
+ subcommand %w(c conv convert), "Convert compose file to resources" do
11
+ parameter "COMPOSE", "the compose file", default: "docker-compose.yml"
12
+ def execute
13
+ song = Siren::Compose.load(compose)
14
+ # open(compose.gsub(/[^.]+$/, 'k8s.yaml'), "w") do |io|
15
+ puts song.to_stack.to_yaml
16
+ # end
17
+ end
18
+ end
19
+
20
+ end
21
+
8
22
  class SongfileCommand < Clamp::Command
9
23
 
10
24
  subcommand %w(c conv convert), "Convert songfile to resources" do
@@ -70,7 +84,8 @@ module CLI
70
84
  end
71
85
  end
72
86
 
73
- subcommand %w(c crypto cryptography), "Cryptography (JOSE) commands", CryptoCommand
87
+ # subcommand %w(c crypto cryptography), "Cryptography (JOSE) commands", CryptoCommand
88
+ subcommand %w(c compose docker-compose), "Docker compose file commands", ComposeCommand
74
89
  subcommand %w(s song songs songfile), "Songfile commands", SongfileCommand
75
90
 
76
91
  end
@@ -0,0 +1,103 @@
1
+ require 'json-schema'
2
+ require 'yaml'
3
+ require_relative 'compose/types'
4
+
5
+ module Siren
6
+
7
+ class Compose
8
+
9
+ attr_reader :name, :xports, :xdomains, :xenv
10
+
11
+ def self.load (filename)
12
+ new(YAML.load(File.read(filename)).deep_compact, filename)
13
+ end
14
+
15
+ def namify (*items)
16
+ items.flatten.compact.join("-").downcase.gsub(/[^a-z\d]/, '-').gsub(/-+/, "-")
17
+ end
18
+
19
+ def initialize (data, filename)
20
+ @filename = filename
21
+ @services = {}
22
+ @networks = {}
23
+ @configs = {}
24
+ @secrets = {}
25
+ @xports = []
26
+ @xdomains = []
27
+ @xenv = {}
28
+ @name = data["x-name"] || namify(File.basename(filename.chomp(File.extname(filename))))
29
+ data = data
30
+ schema = YAML.load(File.read(File.join(Siren::ROOT, "schemas/docker-compose.yaml")))
31
+ begin
32
+ JSON::Validator.validate!(schema, data)
33
+ rescue JSON::Schema::ValidationError => e
34
+ # puts filename
35
+ p e
36
+ exit 1
37
+ end
38
+ data["x-ports"]&.each do |data|
39
+ next unless data["outside"]
40
+ @xports << data
41
+ end
42
+ data["x-domains"]&.each do |data|
43
+ data["name"].gsub! ".altaire.xyz", ".k9.altaire.xyz"
44
+ next unless data["name"] =~ /k9.altaire.xyz$/
45
+ data.delete("path") if data["path"] == ""
46
+ @xdomains << data
47
+ end
48
+ data["x-env"]&.each do |key, value|
49
+ @xenv[key] = value
50
+ end
51
+ data["services"].each do |name, data|
52
+ @services[name] = Service.new(self, {name: name}.merge(data))
53
+ end if data["services"]
54
+ data["networks"].each do |name, data|
55
+ @networks[name] = Network.new(self, {name: name}.merge(data))
56
+ end if data["networks"]
57
+ data["configs"].each do |name, data|
58
+ @configs[name] = Config.new(self, {name: name}.merge(data))
59
+ end if data["configs"]
60
+ data["secrets"].each do |name, data|
61
+ @secrets[name] = Secret.new(self, {name: name}.merge(data))
62
+ end if data["secrets"]
63
+ end
64
+
65
+ def to_stack ()
66
+ stack = Stack.new
67
+ stack << {
68
+ kind: "Namespace",
69
+ apiVersion: "v1",
70
+ metadata: {
71
+ name: name
72
+ },
73
+ }
74
+ stack << {
75
+ kind: "Secret",
76
+ apiVersion: "v1",
77
+ metadata: {
78
+ namespace: name,
79
+ name: "image-pull-secrets",
80
+ },
81
+ data: {
82
+ ".dockerconfigjson": "ewoJImF1dGhzIjogewoJCSJodHRwczovL2FzaWEtbWlycm9yLmdjci5pbyI6IHsKCQkJImF1dGgiOiAiYjJGMWRHZ3lZV05qWlhOemRHOXJaVzQ2ZVdFeU9TNUhiSG95UWtGdk1tTnlZWEJJUkZabllWWTViak5oVFdKWFpFVkNZVWd3UlZNM2RIQXdjVUZzT1ZsdUxUWlRiVVZ5UjFoR1pXUXhhaTAwYlhCMVJYcDFlVlJNU0RSV1dGVlZaMnRyV0VwR1FuZEJhbk5zV2xsYU9HeFJTWFk0VFRKblVUVm5OVEk1TVUxTVQydG9abWN0V2s1VGFVVmpXVWszWld4ZlZIYz0iLAoJCQkiZW1haWwiOiAibm90QHZhbC5pZCIKCQl9LAoJCSJodHRwczovL2FzaWEuZ2NyLmlvIjogewoJCQkiYXV0aCI6ICJiMkYxZEdneVlXTmpaWE56ZEc5clpXNDZlV0V5T1M1SGJIb3lRa0Z2TW1OeVlYQklSRlpuWVZZNWJqTmhUV0pYWkVWQ1lVZ3dSVk0zZEhBd2NVRnNPVmx1TFRaVGJVVnlSMWhHWldReGFpMDBiWEIxUlhwMWVWUk1TRFJXV0ZWVloydHJXRXBHUW5kQmFuTnNXbGxhT0d4UlNYWTRUVEpuVVRWbk5USTVNVTFNVDJ0b1ptY3RXazVUYVVWaldVazNaV3hmVkhjPSIsCgkJCSJlbWFpbCI6ICJub3RAdmFsLmlkIgoJCX0sCgkJImh0dHBzOi8vZXUtbWlycm9yLmdjci5pbyI6IHsKCQkJImF1dGgiOiAiYjJGMWRHZ3lZV05qWlhOemRHOXJaVzQ2ZVdFeU9TNUhiSG95UWtGdk1tTnlZWEJJUkZabllWWTViak5oVFdKWFpFVkNZVWd3UlZNM2RIQXdjVUZzT1ZsdUxUWlRiVVZ5UjFoR1pXUXhhaTAwYlhCMVJYcDFlVlJNU0RSV1dGVlZaMnRyV0VwR1FuZEJhbk5zV2xsYU9HeFJTWFk0VFRKblVUVm5OVEk1TVUxTVQydG9abWN0V2s1VGFVVmpXVWszWld4ZlZIYz0iLAoJCQkiZW1haWwiOiAibm90QHZhbC5pZCIKCQl9LAoJCSJodHRwczovL2V1Lmdjci5pbyI6IHsKCQkJImF1dGgiOiAiYjJGMWRHZ3lZV05qWlhOemRHOXJaVzQ2ZVdFeU9TNUhiSG95UWtGdk1tTnlZWEJJUkZabllWWTViak5oVFdKWFpFVkNZVWd3UlZNM2RIQXdjVUZzT1ZsdUxUWlRiVVZ5UjFoR1pXUXhhaTAwYlhCMVJYcDFlVlJNU0RSV1dGVlZaMnRyV0VwR1FuZEJhbk5zV2xsYU9HeFJTWFk0VFRKblVUVm5OVEk1TVUxTVQydG9abWN0V2s1VGFVVmpXVWszWld4ZlZIYz0iLAoJCQkiZW1haWwiOiAibm90QHZhbC5pZCIKCQl9LAoJCSJodHRwczovL2djci5pbyI6IHsKCQkJImF1dGgiOiAiYjJGMWRHZ3lZV05qWlhOemRHOXJaVzQ2ZVdFeU9TNUhiSG95UWtGdk1tTnlZWEJJUkZabllWWTViak5oVFdKWFpFVkNZVWd3UlZNM2RIQXdjVUZzT1ZsdUxUWlRiVVZ5UjFoR1pXUXhhaTAwYlhCMVJYcDFlVlJNU0RSV1dGVlZaMnRyV0VwR1FuZEJhbk5zV2xsYU9HeFJTWFk0VFRKblVUVm5OVEk1TVUxTVQydG9abWN0V2s1VGFVVmpXVWszWld4ZlZIYz0iLAoJCQkiZW1haWwiOiAibm90QHZhbC5pZCIKCQl9LAoJCSJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOiB7CgkJCSJhdXRoIjogIllXeDBZV2x5Wld4MFpEcGFkbWhpYTNnelJHMTFaMjAwTkVWRVdIUjBlQT09IgoJCX0sCgkJImh0dHBzOi8vbC5nY3IuaW8iOiB7CgkJCSJhdXRoIjogImIyRjFkR2d5WVdOalpYTnpkRzlyWlc0NmVXRXlPUzVIYkhveVFrRnZNbU55WVhCSVJGWm5ZVlk1YmpOaFRXSlhaRVZDWVVnd1JWTTNkSEF3Y1VGc09WbHVMVFpUYlVWeVIxaEdaV1F4YWkwMGJYQjFSWHAxZVZSTVNEUldXRlZWWjJ0cldFcEdRbmRCYW5Oc1dsbGFPR3hSU1hZNFRUSm5VVFZuTlRJNU1VMU1UMnRvWm1jdFdrNVRhVVZqV1VrM1pXeGZWSGM9IiwKCQkJImVtYWlsIjogIm5vdEB2YWwuaWQiCgkJfSwKCQkiaHR0cHM6Ly9sYXVuY2hlci5nY3IuaW8iOiB7CgkJCSJhdXRoIjogImIyRjFkR2d5WVdOalpYTnpkRzlyWlc0NmVXRXlPUzVIYkhveVFrRnZNbU55WVhCSVJGWm5ZVlk1YmpOaFRXSlhaRVZDWVVnd1JWTTNkSEF3Y1VGc09WbHVMVFpUYlVWeVIxaEdaV1F4YWkwMGJYQjFSWHAxZVZSTVNEUldXRlZWWjJ0cldFcEdRbmRCYW5Oc1dsbGFPR3hSU1hZNFRUSm5VVFZuTlRJNU1VMU1UMnRvWm1jdFdrNVRhVVZqV1VrM1pXeGZWSGM9IiwKCQkJImVtYWlsIjogIm5vdEB2YWwuaWQiCgkJfSwKCQkiaHR0cHM6Ly9taXJyb3IuZ2NyLmlvIjogewoJCQkiYXV0aCI6ICJiMkYxZEdneVlXTmpaWE56ZEc5clpXNDZlV0V5T1M1SGJIb3lRa0Z2TW1OeVlYQklSRlpuWVZZNWJqTmhUV0pYWkVWQ1lVZ3dSVk0zZEhBd2NVRnNPVmx1TFRaVGJVVnlSMWhHWldReGFpMDBiWEIxUlhwMWVWUk1TRFJXV0ZWVloydHJXRXBHUW5kQmFuTnNXbGxhT0d4UlNYWTRUVEpuVVRWbk5USTVNVTFNVDJ0b1ptY3RXazVUYVVWaldVazNaV3hmVkhjPSIsCgkJCSJlbWFpbCI6ICJub3RAdmFsLmlkIgoJCX0sCgkJImh0dHBzOi8vdXMtbWlycm9yLmdjci5pbyI6IHsKCQkJImF1dGgiOiAiYjJGMWRHZ3lZV05qWlhOemRHOXJaVzQ2ZVdFeU9TNUhiSG95UWtGdk1tTnlZWEJJUkZabllWWTViak5oVFdKWFpFVkNZVWd3UlZNM2RIQXdjVUZzT1ZsdUxUWlRiVVZ5UjFoR1pXUXhhaTAwYlhCMVJYcDFlVlJNU0RSV1dGVlZaMnRyV0VwR1FuZEJhbk5zV2xsYU9HeFJTWFk0VFRKblVUVm5OVEk1TVUxTVQydG9abWN0V2s1VGFVVmpXVWszWld4ZlZIYz0iLAoJCQkiZW1haWwiOiAibm90QHZhbC5pZCIKCQl9LAoJCSJodHRwczovL3VzLmdjci5pbyI6IHsKCQkJImF1dGgiOiAiYjJGMWRHZ3lZV05qWlhOemRHOXJaVzQ2ZVdFeU9TNUhiSG95UWtGdk1tTnlZWEJJUkZabllWWTViak5oVFdKWFpFVkNZVWd3UlZNM2RIQXdjVUZzT1ZsdUxUWlRiVVZ5UjFoR1pXUXhhaTAwYlhCMVJYcDFlVlJNU0RSV1dGVlZaMnRyV0VwR1FuZEJhbk5zV2xsYU9HeFJTWFk0VFRKblVUVm5OVEk1TVUxTVQydG9abWN0V2s1VGFVVmpXVWszWld4ZlZIYz0iLAoJCQkiZW1haWwiOiAibm90QHZhbC5pZCIKCQl9LAoJCSJyZWdpc3RyeS5hbHRhaXJlLnRlY2g6NTAwMCI6IHsKCQkJImF1dGgiOiAiYm1GMGFHRnVPbTVoZEdoaGJnPT0iCgkJfSwKCQkicmVnaXN0cnkuYWx0YWlyZS54eXoiOiB7CgkJCSJhdXRoIjogIlpHOWphMlZ5T201bGVtNWhkRzFsZFdOamFXZHZZblJ2ZDJwcGJVZHZhbkJoZEhCdmIzSjAiCgkJfQoJfSwKCSJIdHRwSGVhZGVycyI6IHsKCQkiVXNlci1BZ2VudCI6ICJEb2NrZXItQ2xpZW50LzE4LjA5LjUtY2UgKGxpbnV4KSIKCX0KfQ=="
83
+ },
84
+ type: "kubernetes.io/dockerconfigjson"
85
+ }
86
+ @services.each do |name, service|
87
+ service.to_stack(stack)
88
+ end
89
+ @networks.each do |name, network|
90
+ network.to_stack(stack)
91
+ end
92
+ @configs.each do |name, config|
93
+ config.to_stack(stack)
94
+ end
95
+ @secrets.each do |name, secret|
96
+ secret.to_stack(stack)
97
+ end
98
+ stack
99
+ end
100
+
101
+ end
102
+
103
+ end