altaire-siren 0.1.0 → 0.1.2

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 (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