ky 0.2.0 → 0.3.0beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +23 -5
- data/examples/.ky.yml +15 -0
- data/examples/deployment_base.yml +17 -0
- data/examples/dev.deployment.yml +23 -0
- data/examples/dev.yml +4 -0
- data/ky.gemspec +2 -3
- data/lib/ky.rb +55 -10
- data/lib/ky/cli.rb +29 -7
- data/lib/ky/deploy_generation.rb +19 -50
- data/lib/ky/env_generation.rb +21 -7
- data/lib/ky/manipulation.rb +5 -1
- data/lib/ky/template.rb +22 -0
- data/lib/ky/version.rb +1 -1
- data/spec/ky_bin_spec.rb +6 -11
- data/spec/support/web-base.yml +1 -1
- data/spec/support/web-merged.yml +1 -1
- data/templates/deployment.yml +17 -0
- metadata +17 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eff2da2223846540c4f8bb47a3bb59684215b698
|
4
|
+
data.tar.gz: 793e1b97792108e5feada8ec4969cec526a73875
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e02009691a0503ff6d92af8799577792fd9fac9205cfb3c2f7fd9ca88b58c0d2ca38547c95689ee1c646f900488008e534181b1ddf176368fcc337c8a2fe460
|
7
|
+
data.tar.gz: 21727d8f5bbec27b5278b7db6837c508517784c37d33d5300956d85912a53b5318656c150060a122fd2529621f5c8234afae791860139da494a54e81e8283924
|
data/README.md
CHANGED
@@ -4,8 +4,26 @@
|
|
4
4
|
|
5
5
|
The primary purpose is to automate/DRY up duplication and agreement between multiple deployment YAML files and config/secret yaml files that we saw emerging as we built our kubernetes configuration.
|
6
6
|
|
7
|
-
The full/hopeful use of the tool may be enabled with the new `compile` command which is very much a rough draft at present, but which takes a crack at generating a complete deployment yaml file for every line of a Procfile such as used for Heroku, and a pair of config and secrets files. The secret file can be non-base64 encoded, and compile will generate deployments and a base64 encoded secrets file to a target directory specified. This command uses all the below commands in combination,
|
8
|
-
|
7
|
+
The full/hopeful use of the tool may be enabled with the new `compile` command which is very much a rough draft at present, but which takes a crack at generating a complete deployment yaml file for every line of a Procfile such as used for Heroku, and a pair of config and secrets files. The secret file can be non-base64 encoded, and compile will generate deployments and a base64 encoded secrets file to a target directory specified. This command uses all the below commands in combination, one other command not exposed via CLI independently.
|
8
|
+
|
9
|
+
The command is invoked as:
|
10
|
+
`ky compile Procfile.file config.yml secrets.yml output_dir` and the output directory will be created if necessary. You may pass a namespace to compile which will be reflected in the deployments (and should agree with the config and secrets, though it's not checking they agree at present). The arguments are all configurable via the configuration file as well, so it can in practice be invoked as `ky compile` or `kky compile --envioronment stg` if you have a configuration file correctly present as described below.
|
11
|
+
|
12
|
+
Configuration begins with a config file in the project working directory, or in your home directory if you wish to share across several projects. Unfortunately there are several competing conventions for configuration files, the traditional dot-file configuration convention and newer, more visible Capitalfile configuration. KY is a lubricant, and has no opinion, and therefore currently supports naming your configuration file `.ky.yml`, `.ky.yaml`, or `Lubefile` or `Kyfile`. The default configuration, if this file is not found, is as follows:
|
13
|
+
```
|
14
|
+
environments: []
|
15
|
+
replica_count: 1
|
16
|
+
image_pull_policy: "Always"
|
17
|
+
namespace: "default"
|
18
|
+
image: "<YOUR_DOCKER_IMAGE>"
|
19
|
+
image_tag: latest
|
20
|
+
api_version: "extensions/v1beta1"
|
21
|
+
inline_config: true
|
22
|
+
inline_secret: false
|
23
|
+
project_name: "global"
|
24
|
+
```
|
25
|
+
|
26
|
+
Override any or all of these in your file, and the environments files will also prompt KY to look for files named `development.yml` or `development.yaml` in the same directory as the config file itself, if you override environments as `[development]`, or whatever/however many environments as you name. When running a specific environment, configuration from the specific environment will override your global defaults.
|
9
27
|
|
10
28
|
The less automated workflow for the tool might start with generating a yaml file of env mappings from a secrets.yml file and a config.yml file, like so:
|
11
29
|
###Example usage
|
@@ -90,7 +108,7 @@ spec:
|
|
90
108
|
spec:
|
91
109
|
containers:
|
92
110
|
- name: web
|
93
|
-
image:
|
111
|
+
image: docker_image
|
94
112
|
imagePullPolicy: Always
|
95
113
|
ports:
|
96
114
|
- containerPort: 3000
|
@@ -118,7 +136,7 @@ spec:
|
|
118
136
|
spec:
|
119
137
|
containers:
|
120
138
|
- name: web
|
121
|
-
image:
|
139
|
+
image: docker_image
|
122
140
|
imagePullPolicy: Always
|
123
141
|
ports:
|
124
142
|
- containerPort: 3000
|
@@ -185,4 +203,4 @@ $ cat file.yml | obscure decode # reads non-base64 input yaml from stdin, writes
|
|
185
203
|
$ cat file.yml | obscure encode # reads base64 encoded input yaml from stdin, write encoded to stdout
|
186
204
|
```
|
187
205
|
|
188
|
-
A valid url may also be used in place of a file path for input.
|
206
|
+
A valid url may also be used in place of a file path for input.
|
data/examples/.ky.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
environments: [dev, stg, prd]
|
2
|
+
deployment: examples/deployment_base.yml
|
3
|
+
replica_count: 2
|
4
|
+
image_pull_policy: "IfNotPresent"
|
5
|
+
namespace: "default"
|
6
|
+
image: "organization/project"
|
7
|
+
image_tag: "latest"
|
8
|
+
api_version: "extensions/v1beta1"
|
9
|
+
inline_config: true
|
10
|
+
inline_secret: false
|
11
|
+
project_name: "connect"
|
12
|
+
config_path: "spec/support/config.yml"
|
13
|
+
secret_path: "spec/support/decoded.yml"
|
14
|
+
output_dir: "namespaces"
|
15
|
+
procfile_path: "spec/support/Procfile"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
apiVersion: extensions/v1beta1
|
2
|
+
kind: Deployment
|
3
|
+
metadata:
|
4
|
+
name: <%= id %>
|
5
|
+
spec:
|
6
|
+
replicas: <%= replica_count %>
|
7
|
+
template:
|
8
|
+
metadata:
|
9
|
+
labels:
|
10
|
+
app: example-<%= id %>
|
11
|
+
spec:
|
12
|
+
containers:
|
13
|
+
- name: <%= id %>
|
14
|
+
image: organization/project:<%= image_tag %>
|
15
|
+
imagePullPolicy: Always
|
16
|
+
command: <%= command_array.to_s %>
|
17
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
apiVersion: extensions/v1beta1
|
2
|
+
kind: Deployment
|
3
|
+
metadata:
|
4
|
+
name: <%= id %>
|
5
|
+
spec:
|
6
|
+
replicas: <%= replica_count %>
|
7
|
+
template:
|
8
|
+
metadata:
|
9
|
+
labels:
|
10
|
+
app: example-<%= id %>
|
11
|
+
spec:
|
12
|
+
volumes:
|
13
|
+
- name: code
|
14
|
+
persistentVolumeClaim:
|
15
|
+
claimName: code-claim
|
16
|
+
containers:
|
17
|
+
- name: web
|
18
|
+
image: project_dev:latest
|
19
|
+
imagePullPolicy: Always
|
20
|
+
command: <%= command_array.to_s %>
|
21
|
+
volumeMounts:
|
22
|
+
- mountPath: /code
|
23
|
+
name: code
|
data/examples/dev.yml
ADDED
data/ky.gemspec
CHANGED
@@ -16,12 +16,11 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.require_paths = ['lib']
|
17
17
|
s.add_development_dependency 'rspec', '~> 3.5'
|
18
18
|
s.add_development_dependency 'pry', '~> 0.10'
|
19
|
-
s.add_runtime_dependency 'deep_merge', '~> 1.1'
|
20
19
|
s.add_runtime_dependency 'thor', '~> 0.19'
|
21
|
-
s.add_runtime_dependency '
|
20
|
+
s.add_runtime_dependency 'deep_merge', '~> 1.1'
|
22
21
|
|
23
22
|
s.description = <<-DESC
|
24
|
-
Utility belt for
|
23
|
+
Utility belt for generating kubernetes deployment, config and secrets yml files
|
25
24
|
DESC
|
26
25
|
|
27
26
|
s.files = `git ls-files`.split("\n")
|
data/lib/ky.rb
CHANGED
@@ -2,13 +2,31 @@ require 'yaml'
|
|
2
2
|
require 'base64'
|
3
3
|
require 'open-uri'
|
4
4
|
require 'fileutils'
|
5
|
+
require 'pathname'
|
5
6
|
require_relative 'ky/manipulation'
|
6
7
|
require_relative 'ky/env_generation'
|
8
|
+
require_relative 'ky/template'
|
7
9
|
require_relative 'ky/deploy_generation'
|
8
10
|
|
9
11
|
|
10
12
|
module KY
|
13
|
+
CONFIG_FILE_NAMES = [".ky.yml", ".ky.yaml", "Lubefile", "Kyfile"]
|
14
|
+
CONFIG_LOCATIONS = ["#{Dir.pwd}/", "#{Dir.home}/"]
|
15
|
+
DEFAULT_CONFIG = {
|
16
|
+
environments: [],
|
17
|
+
replica_count: 1,
|
18
|
+
image_pull_policy: "Always",
|
19
|
+
namespace: "default",
|
20
|
+
image: "<YOUR_DOCKER_IMAGE>",
|
21
|
+
image_tag: "latest",
|
22
|
+
api_version: "extensions/v1beta1",
|
23
|
+
inline_config: true,
|
24
|
+
inline_secret: false,
|
25
|
+
project_name: "global"
|
26
|
+
}
|
27
|
+
|
11
28
|
module_function
|
29
|
+
cattr_accessor :environment
|
12
30
|
|
13
31
|
def decode(output, input)
|
14
32
|
output << Manipulation.code_yaml(input, :decode)
|
@@ -29,20 +47,47 @@ module KY
|
|
29
47
|
exit(1)
|
30
48
|
end
|
31
49
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
def compile(proc_path, env1path, env2path, output_dir, namespace=DeployGeneration::DEFAULT_NAMESPACE)
|
38
|
-
FileUtils.mkdir_p(output_dir)
|
50
|
+
def compile(proc_path, env1path, env2path, base_output_dir, namespace=DeployGeneration::DEFAULT_NAMESPACE)
|
51
|
+
full_output_dir = Pathname.new(base_output_dir).join(environment.to_s).to_s
|
52
|
+
FileUtils.mkdir_p(full_output_dir)
|
39
53
|
env_obj = EnvGeneration.new(env1path, env2path)
|
40
|
-
deploys_hash = DeployGeneration.new(proc_path,
|
54
|
+
deploys_hash = DeployGeneration.new(proc_path, full_output_dir, env_obj.project, namespace).to_h
|
41
55
|
deploys_hash.each do |file_path, deploy_hash|
|
42
|
-
File.write(file_path,
|
56
|
+
File.write(file_path, Manipulation.merge_hash(deploy_hash, env_obj.to_h).to_yaml)
|
57
|
+
end
|
58
|
+
Manipulation.write_configs_encode_if_needed(env_obj.config_hsh, env_obj.secret_hsh, full_output_dir)
|
59
|
+
end
|
60
|
+
|
61
|
+
def configuration
|
62
|
+
@config ||= begin
|
63
|
+
config = DEFAULT_CONFIG.merge(config_file_location ? YAML.load(File.read(config_file_location)) : {})
|
64
|
+
config = config.merge(current_environment_hash(config)["configuration"] || {})
|
65
|
+
define_methods_from_config(config)
|
66
|
+
config
|
43
67
|
end
|
44
|
-
Manipulation.write_configs_encode_if_needed(env_obj.config_hsh, env_obj.secret_hsh, output_dir)
|
45
68
|
end
|
46
69
|
|
70
|
+
def current_deployment
|
71
|
+
current_environment_hash["deployment"]
|
72
|
+
end
|
73
|
+
|
74
|
+
def current_environment_hash(partial_config=nil)
|
75
|
+
YAML.load(File.read(KY.environment_files(partial_config).find {|file| file.match(KY.environment) })) rescue {}
|
76
|
+
end
|
77
|
+
|
78
|
+
def environment_files(partial_config=nil)
|
79
|
+
environments = (partial_config || configuration)['environments'].flat_map {|env| ["#{env}.yml", "#{env}.yaml"]}
|
80
|
+
(CONFIG_LOCATIONS * environments.count).zip(environments).map(&:join).select {|path| File.exist?(path) && !File.directory?(path) }
|
81
|
+
end
|
82
|
+
|
83
|
+
def config_file_location
|
84
|
+
(CONFIG_LOCATIONS * CONFIG_FILE_NAMES.count).zip(CONFIG_FILE_NAMES).map(&:join).find {|path| File.exist?(path) && !File.directory?(path) }
|
85
|
+
end
|
86
|
+
|
87
|
+
def define_methods_from_config(config)
|
88
|
+
config.keys.each do |key|
|
89
|
+
Template.send(:define_method, key) { config[key] }
|
90
|
+
end
|
91
|
+
end
|
47
92
|
|
48
93
|
end
|
data/lib/ky/cli.rb
CHANGED
@@ -2,6 +2,7 @@ require_relative '../ky'
|
|
2
2
|
require 'thor'
|
3
3
|
module KY
|
4
4
|
class Cli < Thor
|
5
|
+
MissingParametersError = Class.new(StandardError)
|
5
6
|
desc "encode secrets.yml", "base64 encoded yaml version of data attributes in secrets.yml"
|
6
7
|
def encode(input_source=$stdin, output_source=$stdout)
|
7
8
|
input_output(input_source, output_source) do |input_object, output_object|
|
@@ -30,19 +31,40 @@ module KY
|
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
33
|
-
desc "
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
desc "compile Procfile config.yml secrets.yml output", <<-DOC.strip_heredoc
|
35
|
+
Generate kubernetes deployment.yml from Procfile;
|
36
|
+
also generate/copy config/secrets files to output_dir, base64 encode secrets if unencoded.
|
37
|
+
Procfile path may also be specified in configuration as procfile_path
|
38
|
+
ConfigMap.yml file path may also be specified in configuration as config_path
|
39
|
+
secrets.yml file path may also be specified in configuration as secret_path
|
40
|
+
Output directory may also be specified in configuration as output_dir
|
41
|
+
DOC
|
39
42
|
method_option :namespace, type: :string, aliases: "-n"
|
40
|
-
|
43
|
+
method_option :environment, type: :string, aliases: "-e"
|
44
|
+
def compile(procfile_path=nil, config_or_secrets_path=nil, secrets_or_config_path=nil, output_dir=nil)
|
45
|
+
KY.environment = options[:environment]
|
46
|
+
procfile_path ||= KY.configuration['procfile_path']
|
47
|
+
config_or_secrets_path ||= KY.configuration['config_path'] || KY.configuration['secret_path']
|
48
|
+
secrets_or_config_path ||= KY.configuration['secret_path'] || KY.configuration['config_path']
|
49
|
+
output_dir ||= KY.configuration['output_dir']
|
50
|
+
raise MissingParametersError unless procfile_path && config_or_secrets_path && secrets_or_config_path && output_dir
|
41
51
|
input_input(config_or_secrets_path, secrets_or_config_path) do |input1, input2|
|
42
52
|
KY.compile(procfile_path, input1, input2, output_dir, options[:namespace])
|
43
53
|
end
|
44
54
|
end
|
45
55
|
|
56
|
+
desc "example", "copy example configuration and environment override file to current directory"
|
57
|
+
def example
|
58
|
+
puts "Writing dev.yml environment example"
|
59
|
+
`cp #{__dir__}/../../examples/dev.yml .`
|
60
|
+
puts "Writing .ky.yml configuration example"
|
61
|
+
`cp #{__dir__}/../../examples/.ky.yml .`
|
62
|
+
puts "Writing deployment_base.yml template example"
|
63
|
+
`cp #{__dir__}/../../examples/deployment_base.yml .`
|
64
|
+
puts "Writing dev.deployment.yml template-override example"
|
65
|
+
`cp #{__dir__}/../../examples/dev.deployment.yml .`
|
66
|
+
end
|
67
|
+
|
46
68
|
private
|
47
69
|
|
48
70
|
def input_output(input1, output1)
|
data/lib/ky/deploy_generation.rb
CHANGED
@@ -1,27 +1,14 @@
|
|
1
1
|
module KY
|
2
2
|
class DeployGeneration
|
3
|
-
|
4
|
-
IMAGE_TYPE = "docker/image"
|
5
|
-
DEFAULT_PULL_POLICY = "Always"
|
6
|
-
DEFAULT_PROJECT_NAME = "global"
|
7
|
-
DEFAULT_NAMESPACE = "default"
|
8
|
-
DEFAULT_REPLICA_COUNT = 1
|
9
|
-
|
10
|
-
#string array meta-trick to avoid naked strings everywhere below, yaml doesn't to_s symbols as desired
|
11
|
-
%w(apiVersion Deployment imagePullPolicy namespace command
|
12
|
-
replicas template labels app kind containers image
|
13
|
-
data metadata name key valueFrom spec template containers env).each do |raw_string|
|
14
|
-
define_method(raw_string.underscore) { raw_string }
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(proc_path, output_dir, project_name=DEFAULT_PROJECT_NAME, current_namespace=DEFAULT_NAMESPACE)
|
3
|
+
def initialize(proc_path, full_output_dir, project_name=nil, current_namespace=nil)
|
18
4
|
@proc_commands = File.read(proc_path).split("\n")
|
19
5
|
.map {|line| line.split(':', 2) }
|
20
6
|
.map {|k, v| [k, ["/bin/bash","-c", v]] }
|
21
7
|
.to_h
|
22
|
-
@
|
23
|
-
@
|
24
|
-
@current_namespace = current_namespace
|
8
|
+
@full_output_dir = full_output_dir
|
9
|
+
@project_name = project_name || KY.configuration[:project_name]
|
10
|
+
@current_namespace = current_namespace || KY.configuration[:namespace]
|
11
|
+
@deployment_yaml = read_deployment_yaml
|
25
12
|
end
|
26
13
|
|
27
14
|
def call
|
@@ -32,47 +19,29 @@ module KY
|
|
32
19
|
|
33
20
|
def to_h
|
34
21
|
proc_commands.map do |id, command_array|
|
35
|
-
["#{
|
22
|
+
["#{full_output_dir}/#{id}.yml", template_hash(id, command_array)]
|
36
23
|
end.to_h
|
37
24
|
end
|
38
25
|
|
39
26
|
private
|
40
|
-
attr_reader :proc_commands, :
|
27
|
+
attr_reader :proc_commands, :full_output_dir, :project_name, :current_namespace, :deployment_yaml
|
41
28
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
template =>
|
49
|
-
{
|
50
|
-
metadata => {
|
51
|
-
labels =>{ app =>"#{project}-#{id}"}
|
52
|
-
},
|
53
|
-
spec => {
|
54
|
-
containers =>
|
55
|
-
[
|
56
|
-
{
|
57
|
-
name => id,
|
58
|
-
image => IMAGE_TYPE,
|
59
|
-
image_pull_policy => pull_policy,
|
60
|
-
command => command_array
|
61
|
-
}
|
62
|
-
]
|
63
|
-
}
|
64
|
-
}
|
65
|
-
}
|
66
|
-
}
|
29
|
+
def read_deployment_yaml
|
30
|
+
if KY.configuration['deployment']
|
31
|
+
File.read(KY.configuration['deployment'])
|
32
|
+
else
|
33
|
+
File.read(default_deployment_template)
|
34
|
+
end
|
67
35
|
end
|
68
36
|
|
69
|
-
def
|
70
|
-
|
37
|
+
def default_deployment_template
|
38
|
+
"#{__dir__}/../../templates/deployment.yml"
|
71
39
|
end
|
72
40
|
|
73
|
-
def
|
74
|
-
|
41
|
+
def template_hash(id, command_array)
|
42
|
+
app_name = KY.configuration['app_name'] || "#{project_name}-#{id}"
|
43
|
+
template_context = Template.context(app_name: app_name, id: id, command_array: command_array)
|
44
|
+
YAML.load(ERB.new(deployment_yaml).result(template_context))
|
75
45
|
end
|
76
|
-
|
77
46
|
end
|
78
47
|
end
|
data/lib/ky/env_generation.rb
CHANGED
@@ -5,7 +5,7 @@ module KY
|
|
5
5
|
ConflictingProjectError = Class.new(StandardError)
|
6
6
|
|
7
7
|
#string array meta-trick to avoid naked strings everywhere below, yaml doesn't to_s symbols as desired
|
8
|
-
%w(ConfigMap configMapKeyRef Secret secretKeyRef kind data metadata name key valueFrom spec template containers env).each do |raw_string|
|
8
|
+
%w(ConfigMap configMapKeyRef Secret secretKeyRef kind data metadata name key valueFrom value spec template containers env).each do |raw_string|
|
9
9
|
define_method(raw_string.underscore) { raw_string }
|
10
10
|
end
|
11
11
|
|
@@ -22,7 +22,7 @@ module KY
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def to_h
|
25
|
-
output_hash(config_hsh[data].map {|key,
|
25
|
+
output_hash(config_hsh[data].map {|key, value| config_env(key, value) } + secret_hsh[data].map {|key, value| secret_env(key, value) })
|
26
26
|
end
|
27
27
|
|
28
28
|
def project
|
@@ -32,15 +32,29 @@ module KY
|
|
32
32
|
private
|
33
33
|
|
34
34
|
|
35
|
-
def config_env(
|
36
|
-
|
35
|
+
def config_env(kebab_version, value)
|
36
|
+
inline_config? ? inline_env_map(config_map_key_ref, kebab_version, value) : env_map(config_map_key_ref, kebab_version)
|
37
37
|
end
|
38
38
|
|
39
|
-
def secret_env(
|
40
|
-
|
39
|
+
def secret_env(kebab_version, value)
|
40
|
+
inline_secret? ? inline_env_map(secret_key_ref, kebab_version, value) : env_map(secret_key_ref, kebab_version)
|
41
41
|
end
|
42
42
|
|
43
|
-
def
|
43
|
+
def inline_config?
|
44
|
+
KY.configuration[:inline_config]
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def inline_secret?
|
49
|
+
KY.configuration[:inline_secret]
|
50
|
+
end
|
51
|
+
|
52
|
+
def inline_env_map(type, kebab_version, env_value)
|
53
|
+
puts "WARNING: #{kebab_version} format appears incorrect, format as #{kebab_version.dasherize.downcase}" unless kebab_version == kebab_version.dasherize.downcase
|
54
|
+
{name => kebab_version.underscore.upcase, value => env_value }
|
55
|
+
end
|
56
|
+
|
57
|
+
def env_map(type, kebab_version)
|
44
58
|
puts "WARNING: #{kebab_version} format appears incorrect, format as #{kebab_version.dasherize.downcase}" unless kebab_version == kebab_version.dasherize.downcase
|
45
59
|
{name => kebab_version.underscore.upcase, value_from => { type => {name => project, key => kebab_version }}}
|
46
60
|
end
|
data/lib/ky/manipulation.rb
CHANGED
@@ -8,10 +8,14 @@ module KY
|
|
8
8
|
def merge_yaml(input1, input2)
|
9
9
|
combined = {}
|
10
10
|
YAML.load(input1.read).tap { |hsh|
|
11
|
-
hsh
|
11
|
+
merge_hash(hsh, YAML.load(input2.read))
|
12
12
|
}.to_yaml
|
13
13
|
end
|
14
14
|
|
15
|
+
def merge_hash(hsh1, hsh2)
|
16
|
+
hsh1.deeper_merge!(hsh2, merge_hash_arrays: true, extend_existing_arrays: true)
|
17
|
+
end
|
18
|
+
|
15
19
|
def code_yaml(yaml_source, direction)
|
16
20
|
YAML.load(yaml_source.read).tap { |hsh|
|
17
21
|
data = hsh[obscured_data_key]
|
data/lib/ky/template.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
class Template
|
2
|
+
def self.context(hsh)
|
3
|
+
new(hsh).context
|
4
|
+
end
|
5
|
+
|
6
|
+
attr_reader :context_hash
|
7
|
+
def initialize(hsh)
|
8
|
+
@context_hash = hsh
|
9
|
+
end
|
10
|
+
|
11
|
+
def environment
|
12
|
+
KY.environment
|
13
|
+
end
|
14
|
+
|
15
|
+
def context
|
16
|
+
template_context = binding
|
17
|
+
context_hash.each do |var, value|
|
18
|
+
template_context.local_variable_set(var, value)
|
19
|
+
end
|
20
|
+
template_context
|
21
|
+
end
|
22
|
+
end
|
data/lib/ky/version.rb
CHANGED
data/spec/ky_bin_spec.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
require 'ky/cli'
|
2
2
|
describe "cli commands" do
|
3
3
|
let(:tmpfile_path) { "spec/support/tmpfile.yml" }
|
4
|
+
before do # for backwards compatible with old non-inlining test/support behavior
|
5
|
+
normal_config = KY::DEFAULT_CONFIG
|
6
|
+
KY.define_methods_from_config(normal_config)
|
7
|
+
allow(KY).to receive(:configuration).and_return(normal_config.merge(inline_config: false))
|
8
|
+
end
|
9
|
+
|
4
10
|
after { `rm #{tmpfile_path}` if File.exists?(tmpfile_path) }
|
5
11
|
describe "works with stdout" do
|
6
12
|
it "decodes" do
|
@@ -58,17 +64,6 @@ describe "cli commands" do
|
|
58
64
|
end
|
59
65
|
end
|
60
66
|
|
61
|
-
describe "parses Procfile into multiple deployment files" do
|
62
|
-
let(:tmpdir) { 'spec/support/tmpdir' }
|
63
|
-
it "to directory" do
|
64
|
-
KY::Cli.new.from_proc('spec/support/Procfile', tmpdir)
|
65
|
-
expect(File.exists?("#{tmpdir}/web.yml")).to be true
|
66
|
-
expect(File.exists?("#{tmpdir}/worker.yml")).to be true
|
67
|
-
expect(File.exists?("#{tmpdir}/jobs.yml")).to be true
|
68
|
-
`rm -r #{tmpdir}`
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
67
|
describe "compiles Procfile and env secrets/configs into entire deployments" do
|
73
68
|
let(:tmpdir) { 'spec/support/tmpdir' }
|
74
69
|
it "to directory" do
|
data/spec/support/web-base.yml
CHANGED
data/spec/support/web-merged.yml
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
apiVersion: <%= api_version %>
|
2
|
+
kind: Deployment
|
3
|
+
metadata:
|
4
|
+
name: <%= project_name %>
|
5
|
+
namespace: <%= namespace %>
|
6
|
+
spec:
|
7
|
+
replicas: <%= replica_count %>
|
8
|
+
template:
|
9
|
+
metadata:
|
10
|
+
labels:
|
11
|
+
app: <%= app_name %>
|
12
|
+
spec:
|
13
|
+
containers:
|
14
|
+
- name: web
|
15
|
+
image: <%= image %>:<%= image_tag %>
|
16
|
+
imagePullPolicy: <%= image_pull_policy %>
|
17
|
+
command: <%= command_array.to_s %>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ky
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Glusman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.10'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: deep_merge
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '1.1'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '1.1'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: thor
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,27 +53,21 @@ dependencies:
|
|
67
53
|
- !ruby/object:Gem::Version
|
68
54
|
version: '0.19'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
56
|
+
name: deep_merge
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
|
-
- - "
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '3.0'
|
76
|
-
- - "<"
|
59
|
+
- - "~>"
|
77
60
|
- !ruby/object:Gem::Version
|
78
|
-
version: '
|
61
|
+
version: '1.1'
|
79
62
|
type: :runtime
|
80
63
|
prerelease: false
|
81
64
|
version_requirements: !ruby/object:Gem::Requirement
|
82
65
|
requirements:
|
83
|
-
- - "
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: '3.0'
|
86
|
-
- - "<"
|
66
|
+
- - "~>"
|
87
67
|
- !ruby/object:Gem::Version
|
88
|
-
version: '
|
89
|
-
description: " Utility belt for
|
90
|
-
|
68
|
+
version: '1.1'
|
69
|
+
description: " Utility belt for generating kubernetes deployment, config and secrets
|
70
|
+
yml files\n"
|
91
71
|
email:
|
92
72
|
- brian@stellaservice.com
|
93
73
|
executables:
|
@@ -101,12 +81,17 @@ files:
|
|
101
81
|
- LICENSE.txt
|
102
82
|
- README.md
|
103
83
|
- bin/ky
|
84
|
+
- examples/.ky.yml
|
85
|
+
- examples/deployment_base.yml
|
86
|
+
- examples/dev.deployment.yml
|
87
|
+
- examples/dev.yml
|
104
88
|
- ky.gemspec
|
105
89
|
- lib/ky.rb
|
106
90
|
- lib/ky/cli.rb
|
107
91
|
- lib/ky/deploy_generation.rb
|
108
92
|
- lib/ky/env_generation.rb
|
109
93
|
- lib/ky/manipulation.rb
|
94
|
+
- lib/ky/template.rb
|
110
95
|
- lib/ky/version.rb
|
111
96
|
- spec/ky_bin_spec.rb
|
112
97
|
- spec/spec_helper.rb
|
@@ -118,6 +103,7 @@ files:
|
|
118
103
|
- spec/support/web-env.yml
|
119
104
|
- spec/support/web-merged-original.yml
|
120
105
|
- spec/support/web-merged.yml
|
106
|
+
- templates/deployment.yml
|
121
107
|
homepage: https://github.com/stellaservice/ky
|
122
108
|
licenses:
|
123
109
|
- MIT
|
@@ -133,9 +119,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
133
119
|
version: '0'
|
134
120
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
121
|
requirements:
|
136
|
-
- - "
|
122
|
+
- - ">"
|
137
123
|
- !ruby/object:Gem::Version
|
138
|
-
version:
|
124
|
+
version: 1.3.1
|
139
125
|
requirements: []
|
140
126
|
rubyforge_project: ky
|
141
127
|
rubygems_version: 2.5.1
|