formatron 0.1.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 (104) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +12 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +3 -0
  6. data/.simplecov +7 -0
  7. data/.travis.yml +17 -0
  8. data/CODE_OF_CONDUCT.md +13 -0
  9. data/Gemfile +6 -0
  10. data/Guardfile +16 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +93 -0
  13. data/Rakefile +16 -0
  14. data/bin/console +14 -0
  15. data/bin/setup +7 -0
  16. data/exe/formatron +20 -0
  17. data/formatron.gemspec +52 -0
  18. data/lib/formatron.rb +357 -0
  19. data/lib/formatron/aws.rb +197 -0
  20. data/lib/formatron/chef.rb +156 -0
  21. data/lib/formatron/chef/berkshelf.rb +55 -0
  22. data/lib/formatron/chef/keys.rb +48 -0
  23. data/lib/formatron/chef/knife.rb +169 -0
  24. data/lib/formatron/chef_clients.rb +73 -0
  25. data/lib/formatron/cli.rb +33 -0
  26. data/lib/formatron/cli/completion.rb +26 -0
  27. data/lib/formatron/cli/deploy.rb +57 -0
  28. data/lib/formatron/cli/destroy.rb +57 -0
  29. data/lib/formatron/cli/generators/bootstrap.rb +250 -0
  30. data/lib/formatron/cli/generators/credentials.rb +100 -0
  31. data/lib/formatron/cli/generators/instance.rb +118 -0
  32. data/lib/formatron/cli/provision.rb +59 -0
  33. data/lib/formatron/cloud_formation.rb +54 -0
  34. data/lib/formatron/cloud_formation/resources/cloud_formation.rb +27 -0
  35. data/lib/formatron/cloud_formation/resources/ec2.rb +336 -0
  36. data/lib/formatron/cloud_formation/resources/iam.rb +94 -0
  37. data/lib/formatron/cloud_formation/resources/route53.rb +54 -0
  38. data/lib/formatron/cloud_formation/scripts.rb +128 -0
  39. data/lib/formatron/cloud_formation/template.rb +114 -0
  40. data/lib/formatron/cloud_formation/template/parameters.rb +20 -0
  41. data/lib/formatron/cloud_formation/template/vpc.rb +181 -0
  42. data/lib/formatron/cloud_formation/template/vpc/subnet.rb +187 -0
  43. data/lib/formatron/cloud_formation/template/vpc/subnet/acl.rb +147 -0
  44. data/lib/formatron/cloud_formation/template/vpc/subnet/bastion.rb +66 -0
  45. data/lib/formatron/cloud_formation/template/vpc/subnet/chef_server.rb +205 -0
  46. data/lib/formatron/cloud_formation/template/vpc/subnet/instance.rb +162 -0
  47. data/lib/formatron/cloud_formation/template/vpc/subnet/instance/policy.rb +74 -0
  48. data/lib/formatron/cloud_formation/template/vpc/subnet/instance/security_group.rb +117 -0
  49. data/lib/formatron/cloud_formation/template/vpc/subnet/instance/setup.rb +68 -0
  50. data/lib/formatron/cloud_formation/template/vpc/subnet/nat.rb +94 -0
  51. data/lib/formatron/completion.rb +26 -0
  52. data/lib/formatron/completion/completion.sh.erb +35 -0
  53. data/lib/formatron/config.rb +31 -0
  54. data/lib/formatron/config/reader.rb +29 -0
  55. data/lib/formatron/dsl.rb +15 -0
  56. data/lib/formatron/dsl/formatron.rb +25 -0
  57. data/lib/formatron/dsl/formatron/global.rb +19 -0
  58. data/lib/formatron/dsl/formatron/global/ec2.rb +17 -0
  59. data/lib/formatron/dsl/formatron/vpc.rb +17 -0
  60. data/lib/formatron/dsl/formatron/vpc/subnet.rb +27 -0
  61. data/lib/formatron/dsl/formatron/vpc/subnet/acl.rb +18 -0
  62. data/lib/formatron/dsl/formatron/vpc/subnet/chef_server.rb +32 -0
  63. data/lib/formatron/dsl/formatron/vpc/subnet/chef_server/organization.rb +22 -0
  64. data/lib/formatron/dsl/formatron/vpc/subnet/instance.rb +29 -0
  65. data/lib/formatron/dsl/formatron/vpc/subnet/instance/chef.rb +22 -0
  66. data/lib/formatron/dsl/formatron/vpc/subnet/instance/policy.rb +21 -0
  67. data/lib/formatron/dsl/formatron/vpc/subnet/instance/policy/statement.rb +23 -0
  68. data/lib/formatron/dsl/formatron/vpc/subnet/instance/security_group.rb +21 -0
  69. data/lib/formatron/dsl/formatron/vpc/subnet/instance/setup.rb +22 -0
  70. data/lib/formatron/dsl/formatron/vpc/subnet/instance/setup/variable.rb +23 -0
  71. data/lib/formatron/external.rb +61 -0
  72. data/lib/formatron/external/dsl.rb +171 -0
  73. data/lib/formatron/external/outputs.rb +25 -0
  74. data/lib/formatron/generators/bootstrap.rb +90 -0
  75. data/lib/formatron/generators/bootstrap/config.rb +62 -0
  76. data/lib/formatron/generators/bootstrap/ec2.rb +17 -0
  77. data/lib/formatron/generators/bootstrap/formatronfile.rb +52 -0
  78. data/lib/formatron/generators/bootstrap/formatronfile/Formatronfile.erb +79 -0
  79. data/lib/formatron/generators/bootstrap/ssl.rb +35 -0
  80. data/lib/formatron/generators/credentials.rb +17 -0
  81. data/lib/formatron/generators/instance.rb +64 -0
  82. data/lib/formatron/generators/instance/config.rb +47 -0
  83. data/lib/formatron/generators/instance/formatronfile.rb +47 -0
  84. data/lib/formatron/generators/instance/formatronfile/Formatronfile.erb +16 -0
  85. data/lib/formatron/generators/util.rb +14 -0
  86. data/lib/formatron/generators/util/cookbook.rb +65 -0
  87. data/lib/formatron/generators/util/gitignore.rb +16 -0
  88. data/lib/formatron/generators/util/readme.rb +18 -0
  89. data/lib/formatron/logger.rb +8 -0
  90. data/lib/formatron/s3/chef_server_cert.rb +85 -0
  91. data/lib/formatron/s3/chef_server_keys.rb +103 -0
  92. data/lib/formatron/s3/cloud_formation_template.rb +61 -0
  93. data/lib/formatron/s3/configuration.rb +58 -0
  94. data/lib/formatron/s3/path.rb +30 -0
  95. data/lib/formatron/util/dsl.rb +107 -0
  96. data/lib/formatron/util/shell.rb +20 -0
  97. data/lib/formatron/util/vpc.rb +15 -0
  98. data/lib/formatron/version.rb +4 -0
  99. data/support/cloudformation_describe_stacks_response.rb +36 -0
  100. data/support/dsl_test.rb +123 -0
  101. data/support/route53_get_hosted_zone_response.rb +21 -0
  102. data/support/s3_get_object_response.rb +21 -0
  103. data/support/template_test.rb +41 -0
  104. metadata +414 -0
@@ -0,0 +1,16 @@
1
+ class Formatron
2
+ module Generators
3
+ module Util
4
+ # generates placeholder README.md
5
+ module Gitignore
6
+ def self.write(directory)
7
+ FileUtils.mkdir_p directory
8
+ readme = File.join directory, '.gitignore'
9
+ File.write readme, <<-EOH.gsub(/^ {12}/, '')
10
+ /.formatron/
11
+ EOH
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ class Formatron
2
+ module Generators
3
+ module Util
4
+ # generates placeholder README.md
5
+ module Readme
6
+ def self.write(directory, name)
7
+ FileUtils.mkdir_p directory
8
+ readme = File.join directory, 'README.md'
9
+ File.write readme, <<-EOH.gsub(/^ {12}/, '')
10
+ # #{name}
11
+
12
+ Formatron configuration
13
+ EOH
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ require 'logger'
2
+
3
+ # add logger to class
4
+ class Formatron
5
+ LOG = Logger.new($stdout).tap do |log|
6
+ log.progname = 'Formatron'
7
+ end
8
+ end
@@ -0,0 +1,85 @@
1
+ require_relative 'path'
2
+ require 'formatron/logger'
3
+
4
+ class Formatron
5
+ module S3
6
+ # manage the Chef Server SSL certificate and key stored on S3
7
+ module ChefServerCert
8
+ CERT_NAME = 'ssl.cert'
9
+ KEY_NAME = 'ssl.key'
10
+
11
+ # rubocop:disable Metrics/ParameterLists
12
+ # rubocop:disable Metrics/MethodLength
13
+ def self.deploy(
14
+ aws:,
15
+ kms_key:,
16
+ bucket:,
17
+ name:,
18
+ target:,
19
+ guid:,
20
+ cert:,
21
+ key:
22
+ )
23
+ cert_key = self.cert_key name: name, target: target, guid: guid
24
+ Formatron::LOG.info do
25
+ "Upload Chef Server SSL certifcate to #{bucket}/#{cert_key}"
26
+ end
27
+ aws.upload_file(
28
+ kms_key: kms_key,
29
+ bucket: bucket,
30
+ key: cert_key,
31
+ content: cert
32
+ )
33
+ key_key = self.key_key name: name, target: target, guid: guid
34
+ Formatron::LOG.info do
35
+ "Upload Chef Server SSL key to #{bucket}/#{key_key}"
36
+ end
37
+ aws.upload_file(
38
+ kms_key: kms_key,
39
+ bucket: bucket,
40
+ key: key_key,
41
+ content: key
42
+ )
43
+ end
44
+ # rubocop:enable Metrics/MethodLength
45
+ # rubocop:enable Metrics/ParameterLists
46
+
47
+ # rubocop:disable Metrics/MethodLength
48
+ def self.destroy(aws:, bucket:, name:, target:, guid:)
49
+ cert_key = self.cert_key name: name, target: target, guid: guid
50
+ Formatron::LOG.info do
51
+ "Delete Chef Server SSL certificate from #{bucket}/#{cert_key}"
52
+ end
53
+ aws.delete_file(
54
+ bucket: bucket,
55
+ key: cert_key
56
+ )
57
+ key_key = self.key_key name: name, target: target, guid: guid
58
+ Formatron::LOG.info do
59
+ "Delete Chef Server SSL key from #{bucket}/#{key_key}"
60
+ end
61
+ aws.delete_file(
62
+ bucket: bucket,
63
+ key: key_key
64
+ )
65
+ end
66
+ # rubocop:enable Metrics/MethodLength
67
+
68
+ def self.cert_key(name:, target:, guid:)
69
+ Path.key(
70
+ name: name,
71
+ target: target,
72
+ sub_key: "#{guid}/#{CERT_NAME}"
73
+ )
74
+ end
75
+
76
+ def self.key_key(name:, target:, guid:)
77
+ Path.key(
78
+ name: name,
79
+ target: target,
80
+ sub_key: "#{guid}/#{KEY_NAME}"
81
+ )
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,103 @@
1
+ require_relative 'path'
2
+ require 'formatron/logger'
3
+
4
+ class Formatron
5
+ module S3
6
+ # manage the Chef Server user and organization keys
7
+ module ChefServerKeys
8
+ USER_PEM_NAME = 'user.pem'
9
+ ORGANIZATION_PEM_NAME = 'organization.pem'
10
+
11
+ # rubocop:disable Metrics/MethodLength
12
+ # rubocop:disable Metrics/ParameterLists
13
+ def self.get(
14
+ aws:,
15
+ bucket:,
16
+ name:,
17
+ target:,
18
+ guid:,
19
+ directory:
20
+ )
21
+ user_pem_key = self.user_pem_key name: name, target: target, guid: guid
22
+ Formatron::LOG.info do
23
+ 'Download Chef Server user key from ' \
24
+ "#{bucket}/#{user_pem_key}"
25
+ end
26
+ aws.download_file(
27
+ bucket: bucket,
28
+ key: user_pem_key,
29
+ path: user_pem_path(directory: directory)
30
+ )
31
+ organization_pem_key = self.organization_pem_key(
32
+ name: name, target: target, guid: guid
33
+ )
34
+ Formatron::LOG.info do
35
+ 'Download Chef Server organization key ' \
36
+ "from #{bucket}/#{organization_pem_key}"
37
+ end
38
+ aws.download_file(
39
+ bucket: bucket,
40
+ key: organization_pem_key,
41
+ path: organization_pem_path(directory: directory)
42
+ )
43
+ end
44
+ # rubocop:enable Metrics/ParameterLists
45
+ # rubocop:enable Metrics/MethodLength
46
+
47
+ # rubocop:disable Metrics/MethodLength
48
+ def self.destroy(
49
+ aws:,
50
+ bucket:,
51
+ name:,
52
+ target:,
53
+ guid:
54
+ )
55
+ user_pem_key = self.user_pem_key name: name, target: target, guid: guid
56
+ Formatron::LOG.info do
57
+ 'Delete Chef Server user key from ' \
58
+ "#{bucket}/#{user_pem_key}"
59
+ end
60
+ aws.delete_file(
61
+ bucket: bucket,
62
+ key: user_pem_key
63
+ )
64
+ organization_pem_key = self.organization_pem_key(
65
+ name: name, target: target, guid: guid
66
+ )
67
+ Formatron::LOG.info do
68
+ 'Delete Chef Server organization key ' \
69
+ "from #{bucket}/#{organization_pem_key}"
70
+ end
71
+ aws.delete_file(
72
+ bucket: bucket,
73
+ key: organization_pem_key
74
+ )
75
+ end
76
+ # rubocop:enable Metrics/MethodLength
77
+
78
+ def self.user_pem_key(name:, target:, guid:)
79
+ Path.key(
80
+ name: name,
81
+ target: target,
82
+ sub_key: "#{guid}/#{USER_PEM_NAME}"
83
+ )
84
+ end
85
+
86
+ def self.user_pem_path(directory:)
87
+ File.join directory, USER_PEM_NAME
88
+ end
89
+
90
+ def self.organization_pem_key(name:, target:, guid:)
91
+ Path.key(
92
+ name: name,
93
+ target: target,
94
+ sub_key: "#{guid}/#{ORGANIZATION_PEM_NAME}"
95
+ )
96
+ end
97
+
98
+ def self.organization_pem_path(directory:)
99
+ File.join directory, ORGANIZATION_PEM_NAME
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,61 @@
1
+ require_relative 'path'
2
+ require 'formatron/logger'
3
+
4
+ class Formatron
5
+ module S3
6
+ # manage the CloudFormation template stored on S3
7
+ module CloudFormationTemplate
8
+ FILE_NAME = 'cloud_formation_template.json'
9
+
10
+ # rubocop:disable Metrics/ParameterLists
11
+ # rubocop:disable Metrics/MethodLength
12
+ def self.deploy(
13
+ aws:, kms_key:, bucket:, name:, target:, cloud_formation_template:
14
+ )
15
+ key = Path.key(
16
+ name: name,
17
+ target: target,
18
+ sub_key: FILE_NAME
19
+ )
20
+ Formatron::LOG.info do
21
+ "Upload CloudFormation template to #{bucket}/#{key}"
22
+ end
23
+ aws.upload_file(
24
+ kms_key: kms_key,
25
+ bucket: bucket,
26
+ key: key,
27
+ content: cloud_formation_template
28
+ )
29
+ end
30
+ # rubocop:enable Metrics/MethodLength
31
+ # rubocop:enable Metrics/ParameterLists
32
+
33
+ # rubocop:disable Metrics/MethodLength
34
+ def self.destroy(aws:, bucket:, name:, target:)
35
+ key = Path.key(
36
+ name: name,
37
+ target: target,
38
+ sub_key: FILE_NAME
39
+ )
40
+ Formatron::LOG.info do
41
+ "Delete CloudFormation template from #{bucket}/#{key}"
42
+ end
43
+ aws.delete_file(
44
+ bucket: bucket,
45
+ key: key
46
+ )
47
+ end
48
+ # rubocop:enable Metrics/MethodLength
49
+
50
+ def self.url(region:, bucket:, name:, target:)
51
+ Path.url(
52
+ region: region,
53
+ bucket: bucket,
54
+ name: name,
55
+ target: target,
56
+ sub_key: FILE_NAME
57
+ )
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,58 @@
1
+ require_relative 'path'
2
+ require 'formatron/logger'
3
+
4
+ class Formatron
5
+ module S3
6
+ # manage the configuration stored on S3
7
+ module Configuration
8
+ FILE_NAME = 'configuration.json'
9
+
10
+ # rubocop:disable Metrics/ParameterLists
11
+ def self.deploy(aws:, kms_key:, bucket:, name:, target:, configuration:)
12
+ key = self.key name: name, target: target
13
+ Formatron::LOG.info do
14
+ "Upload configuration to #{bucket}/#{key}"
15
+ end
16
+ aws.upload_file(
17
+ kms_key: kms_key,
18
+ bucket: bucket,
19
+ key: key,
20
+ content: "#{JSON.pretty_generate(configuration)}\n"
21
+ )
22
+ end
23
+ # rubocop:enable Metrics/ParameterLists
24
+
25
+ def self.get(aws:, bucket:, name:, target:)
26
+ key = self.key name: name, target: target
27
+ Formatron::LOG.info do
28
+ "Get configuration from #{bucket}/#{key}"
29
+ end
30
+ JSON.parse(
31
+ aws.get_file(
32
+ bucket: bucket,
33
+ key: key
34
+ )
35
+ )
36
+ end
37
+
38
+ def self.destroy(aws:, bucket:, name:, target:)
39
+ key = self.key name: name, target: target
40
+ Formatron::LOG.info do
41
+ "Delete configuration from #{bucket}/#{key}"
42
+ end
43
+ aws.delete_file(
44
+ bucket: bucket,
45
+ key: key
46
+ )
47
+ end
48
+
49
+ def self.key(name:, target:)
50
+ Path.key(
51
+ name: name,
52
+ target: target,
53
+ sub_key: FILE_NAME
54
+ )
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,30 @@
1
+ class Formatron
2
+ module S3
3
+ # defines the S3 bucket keys for consistency
4
+ module Path
5
+ def self.key(name:, target:, sub_key:)
6
+ File.join _base_path(
7
+ name: name,
8
+ target: target
9
+ ), sub_key
10
+ end
11
+
12
+ def self.url(region:, bucket:, name:, target:, sub_key:)
13
+ key = key(
14
+ name: name,
15
+ target: target,
16
+ sub_key: sub_key
17
+ )
18
+ "https://s3-#{region}.amazonaws.com/#{bucket}/#{key}"
19
+ end
20
+
21
+ def self._base_path(name:, target:)
22
+ File.join target, name
23
+ end
24
+
25
+ private_class_method(
26
+ :_base_path
27
+ )
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,107 @@
1
+ class Formatron
2
+ module Util
3
+ # utilities for generating DSL classes
4
+ module DSL
5
+ def dsl_initialize_block(&block)
6
+ define_method :initialize do |**params|
7
+ instance_exec(**params, &block) unless block.nil?
8
+ end
9
+ end
10
+
11
+ def dsl_initialize_hash(&block)
12
+ define_method :initialize do |dsl_key, **params|
13
+ instance_exec(
14
+ dsl_key,
15
+ **params,
16
+ &block
17
+ ) unless block.nil?
18
+ end
19
+ end
20
+
21
+ def dsl_property(symbol)
22
+ iv = "@#{symbol}"
23
+ define_method symbol do |value = nil|
24
+ instance_variable_set iv, value unless value.nil?
25
+ instance_variable_get iv
26
+ end
27
+ end
28
+
29
+ # rubocop:disable Metrics/MethodLength
30
+ def dsl_block(symbol, cls, &params_block)
31
+ iv = "@#{symbol}"
32
+ define_method symbol do |&block|
33
+ value = instance_variable_get(iv)
34
+ if value.nil?
35
+ params = {}
36
+ params = instance_eval(
37
+ &params_block
38
+ ) unless params_block.nil?
39
+ value = self.class.const_get(cls).new(**params)
40
+ instance_variable_set iv, value
41
+ end
42
+ block.call value unless block.nil?
43
+ instance_variable_get iv
44
+ end
45
+ end
46
+ # rubocop:enable Metrics/MethodLength
47
+
48
+ # rubocop:disable Metrics/MethodLength
49
+ def dsl_hash(symbol, cls, &params_block)
50
+ iv = "@#{symbol}"
51
+ define_method symbol do |dsl_key = nil, &block|
52
+ hash = instance_variable_get(iv)
53
+ if hash.nil?
54
+ hash = {}
55
+ instance_variable_set iv, hash
56
+ end
57
+ unless dsl_key.nil?
58
+ params = {}
59
+ params = instance_exec(
60
+ dsl_key, &params_block
61
+ ) unless params_block.nil?
62
+ value = self.class.const_get(cls).new(
63
+ dsl_key,
64
+ **params
65
+ )
66
+ hash[dsl_key] = value
67
+ block.call value unless block.nil?
68
+ end
69
+ hash
70
+ end
71
+ end
72
+ # rubocop:enable Metrics/MethodLength
73
+
74
+ def dsl_array(symbol)
75
+ iv = "@#{symbol}"
76
+ define_method symbol do |value = nil|
77
+ array = instance_variable_get(iv)
78
+ if array.nil?
79
+ array = []
80
+ instance_variable_set iv, array
81
+ end
82
+ array.push value unless value.nil?
83
+ array
84
+ end
85
+ end
86
+
87
+ # rubocop:disable Metrics/MethodLength
88
+ def dsl_block_array(symbol, cls)
89
+ iv = "@#{symbol}"
90
+ define_method symbol do |&block|
91
+ array = instance_variable_get(iv)
92
+ if array.nil?
93
+ array = []
94
+ instance_variable_set iv, array
95
+ end
96
+ unless block.nil?
97
+ value = self.class.const_get(cls).new
98
+ array.push value
99
+ block.call value
100
+ end
101
+ array
102
+ end
103
+ end
104
+ # rubocop:enable Metrics/MethodLength
105
+ end
106
+ end
107
+ end