ky 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 80b326de6d0dd57558007807fe7441ea72f75c2e
4
- data.tar.gz: 7788d551ece1c5bdafd05c99ea05a4a16a5d4b88
3
+ metadata.gz: 88f4ea27998f9a2958de3c9e2bdf989de7d99110
4
+ data.tar.gz: 2fd156270734c5064cd94d47e4f79d8a734e8658
5
5
  SHA512:
6
- metadata.gz: 3ff01e43e12fa0db1a2649c5f9b410572012f512c59a41445cb106be7b0902c406a3e3a26146fdc2b539ff465f6e2104576ab96ccf27a04d73a1efb2c4ed4384
7
- data.tar.gz: 8614bfdae5d0aab41b98c4eedfb3668f54106dde827429f0397fc894042616e3ea3bb81305d317612aa8a09464b911b55aa34b551c6403ea97c95b4f1ab71ef5
6
+ metadata.gz: fb7b698da20ddb79a6aba30ee1e4fdba2983cd319bd08dae0325cbacabf4c60c50cfed7aafe5f074a80f3bd1af3d880755d6851eb30821c89adaa6bbaf9abf0e
7
+ data.tar.gz: 5da3f95409421d0f5b3974283a8cb6187b9174cf043e35268ce979878b942dd2565218fea461d8f43855c982fae8af7bd3f4a3316c69515f644b2a4932588c21
data/README.md CHANGED
@@ -4,8 +4,10 @@
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, plus the undocumented `from_proc` command. The command is invoked as:
8
+ `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).
7
9
 
8
- The typical 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:
10
+ 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:
9
11
  ###Example usage
10
12
  Assuming config.yml such as:
11
13
  ```
data/lib/ky.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'yaml'
2
2
  require 'base64'
3
3
  require 'open-uri'
4
+ require 'fileutils'
4
5
  require_relative 'ky/manipulation'
5
6
  require_relative 'ky/env_generation'
6
7
  require_relative 'ky/deploy_generation'
@@ -22,15 +23,26 @@ module KY
22
23
  end
23
24
 
24
25
  def env(output, input1, input2)
25
- output << EnvGeneration.generate_env(input1, input2)
26
+ output << EnvGeneration.generate_env(input1, input2).to_yaml
26
27
  rescue KY::EnvGeneration::ConflictingProjectError => e
27
28
  $stderr << "Error processing yml files, please provide a config and a secrets file from the same kubernetes project/name"
28
29
  exit(1)
29
30
  end
30
31
 
31
32
  def from_proc(proc_path, output_dir)
33
+ FileUtils.mkdir_p(output_dir)
32
34
  DeployGeneration.new(proc_path, output_dir).call
33
35
  end
34
36
 
37
+ def compile(proc_path, env1path, env2path, output_dir, namespace=DeployGeneration::DEFAULT_NAMESPACE)
38
+ FileUtils.mkdir_p(output_dir)
39
+ env_obj = EnvGeneration.new(env1path, env2path)
40
+ deploys_hash = DeployGeneration.new(proc_path, output_dir, env_obj.project, namespace).to_h
41
+ deploys_hash.each do |file_path, deploy_hash|
42
+ File.write(file_path, deploy_hash.merge(env_obj.to_h).to_yaml)
43
+ end
44
+ Manipulation.write_configs_encode_if_needed(env_obj.config_hsh, env_obj.secret_hsh, output_dir)
45
+ end
46
+
35
47
 
36
48
  end
@@ -30,17 +30,29 @@ module KY
30
30
  end
31
31
  end
32
32
 
33
- desc "from_proc path/to/Procfile output_dir", "generate kubernetes deployment base configs from Procfile"
33
+ desc "from_proc Procfile.file output_dir", "generate kubernetes deployment base configs from Procfile to output_dir"
34
34
  def from_proc(procfile_path, output_dir)
35
35
  KY.from_proc(procfile_path, output_dir)
36
36
  end
37
37
 
38
+ desc "compile Procfile.file config.yml secrets.yml output_dir", "generate kubernetes deployment configs from Procfile and env files to output_dir, encode secrets if unencoded"
39
+ method_option :namespace, type: :string, aliases: "-n"
40
+ def compile(procfile_path, config_or_secrets_path, secrets_or_config_path, output_dir)
41
+ input_input(config_or_secrets_path, secrets_or_config_path) do |input1, input2|
42
+ KY.compile(procfile_path, input1, input2, output_dir, options[:namespace])
43
+ end
44
+ end
45
+
38
46
  private
39
47
 
40
48
  def input_output(input1, output1)
41
49
  with(input1, 'r') {|input_object| with(output1, 'w+') { |output_object| yield(input_object, output_object) } }
42
50
  end
43
51
 
52
+ def input_input(input1, input2)
53
+ with(input1, 'r') {|input_object1| with(input2, 'r') { |input_object2| yield(input_object1, input_object2) } }
54
+ end
55
+
44
56
  def with(output, mode)
45
57
  if output.kind_of?(IO)
46
58
  yield output
@@ -0,0 +1,78 @@
1
+ module KY
2
+ class DeployGeneration
3
+ API_VERSION = "extensions/v1beta1"
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)
18
+ @proc_commands = File.read(proc_path).split("\n")
19
+ .map {|line| line.split(':', 2) }
20
+ .map {|k, v| [k, ["/bin/bash","-c", v]] }
21
+ .to_h
22
+ @output_dir = output_dir
23
+ @project = project_name
24
+ @current_namespace = current_namespace
25
+ end
26
+
27
+ def call
28
+ to_h.each do |file_path, deploy_hash|
29
+ File.write(file_path, deploy_hash.to_yaml)
30
+ end
31
+ end
32
+
33
+ def to_h
34
+ proc_commands.map do |id, command_array|
35
+ ["#{output_dir}/#{id}.yml", template_hash(id, command_array)]
36
+ end.to_h
37
+ end
38
+
39
+ private
40
+ attr_reader :proc_commands, :output_dir, :project, :current_namespace
41
+
42
+ def template_hash(id, command_array)
43
+ {api_version => API_VERSION,
44
+ kind => deployment,
45
+ metadata =>{ name => id, namespace => current_namespace},
46
+ spec =>
47
+ {replicas => replica_count,
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
+ }
67
+ end
68
+
69
+ def replica_count
70
+ ENV['REPLICA_COUNT'] || DEFAULT_REPLICA_COUNT
71
+ end
72
+
73
+ def pull_policy
74
+ ENV['PULL_POLICY'] || DEFAULT_PULL_POLICY
75
+ end
76
+
77
+ end
78
+ end
@@ -10,7 +10,7 @@ module KY
10
10
  end
11
11
 
12
12
  def self.generate_env(input1, input2)
13
- new(input1, input2).to_yaml
13
+ new(input1, input2).to_h
14
14
  end
15
15
 
16
16
  attr_reader :config_hsh, :secret_hsh
@@ -21,16 +21,17 @@ module KY
21
21
  raise ConflictingProjectError.new("Config and Secret metadata names do not agree") unless secret_hsh[metadata][name] == project
22
22
  end
23
23
 
24
- def to_yaml
25
- output_hash(config_hsh[data].map {|key, _| config_env(project, key) } + secret_hsh[data].map {|key, _| secret_env(project, key) }).to_yaml
24
+ def to_h
25
+ output_hash(config_hsh[data].map {|key, _| config_env(project, key) } + secret_hsh[data].map {|key, _| secret_env(project, key) })
26
26
  end
27
27
 
28
- private
29
-
30
28
  def project
31
29
  config_hsh[metadata][name]
32
30
  end
33
31
 
32
+ private
33
+
34
+
34
35
  def config_env(project, kebab_version)
35
36
  env_map(config_map_key_ref, project, kebab_version)
36
37
  end
@@ -3,7 +3,7 @@ module KY
3
3
  module Manipulation
4
4
  DEFAULT_DATA_KEY = 'data'
5
5
  MAGIC_DELIMITER = '@'
6
-
6
+ BASE_64_DETECTION_REGEX = /^([A-Za-z0-9+]{4})*([A-Za-z0-9+]{4}|[A-Za-z0-9+]{3}=|[A-Za-z0-9+]{2}==)$/
7
7
  class << self
8
8
  def merge_yaml(input1, input2)
9
9
  combined = {}
@@ -41,6 +41,16 @@ module KY
41
41
  def obscured_data_key
42
42
  ENV['DATA_KEY'] || DEFAULT_DATA_KEY
43
43
  end
44
+
45
+ def write_configs_encode_if_needed(config_hsh, secret_hsh, output_path)
46
+ if secret_hsh[obscured_data_key].values.detect {|value| BASE_64_DETECTION_REGEX =~ value }
47
+ File.write("#{output_path}/secret.yml", secret_hsh.to_yaml)
48
+ else
49
+ File.write("#{output_path}/secret.yml", code_yaml(StringIO.new(secret_hsh.to_yaml), :encode))
50
+ end
51
+ File.write("#{output_path}/config.yml", config_hsh.to_yaml)
52
+ end
53
+
44
54
  end
45
55
  end
46
56
  end
@@ -1,3 +1,3 @@
1
1
  module KY
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -65,6 +65,18 @@ describe "cli commands" do
65
65
  expect(File.exists?("#{tmpdir}/web.yml")).to be true
66
66
  expect(File.exists?("#{tmpdir}/worker.yml")).to be true
67
67
  expect(File.exists?("#{tmpdir}/jobs.yml")).to be true
68
+ `rm -r #{tmpdir}`
69
+ end
70
+ end
71
+
72
+ describe "compiles Procfile and env secrets/configs into entire deployments" do
73
+ let(:tmpdir) { 'spec/support/tmpdir' }
74
+ it "to directory" do
75
+ KY::Cli.new.compile('spec/support/Procfile', 'spec/support/config.yml', 'spec/support/decoded.yml', tmpdir)
76
+ expect(File.exists?("#{tmpdir}/web.yml")).to be true
77
+ expect(File.exists?("#{tmpdir}/worker.yml")).to be true
78
+ expect(File.exists?("#{tmpdir}/jobs.yml")).to be true
79
+ `rm -r #{tmpdir}`
68
80
  end
69
81
  end
70
82
 
@@ -0,0 +1,3 @@
1
+ web: bundle exec puma -C ./config/puma.rb
2
+ jobs: bundle exec rake jobs:work
3
+ worker: bundle exec toiler --rails -C config/toiler.yml
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ky
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Glusman
@@ -104,11 +104,13 @@ files:
104
104
  - ky.gemspec
105
105
  - lib/ky.rb
106
106
  - lib/ky/cli.rb
107
+ - lib/ky/deploy_generation.rb
107
108
  - lib/ky/env_generation.rb
108
109
  - lib/ky/manipulation.rb
109
110
  - lib/ky/version.rb
110
111
  - spec/ky_bin_spec.rb
111
112
  - spec/spec_helper.rb
113
+ - spec/support/Procfile
112
114
  - spec/support/config.yml
113
115
  - spec/support/decoded.yml
114
116
  - spec/support/encoded.yml