idlc-sdk-pfm 1.0.0.pre.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/.yardopts +3 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +37 -0
  9. data/Rakefile +6 -0
  10. data/bin/pfm +8 -0
  11. data/docs/GettingStarted.md +299 -0
  12. data/idlc-sdk-pfm.gemspec +44 -0
  13. data/lib/idlc-sdk-pfm/builtin_commands.rb +11 -0
  14. data/lib/idlc-sdk-pfm/cli.rb +150 -0
  15. data/lib/idlc-sdk-pfm/command/apply.rb +71 -0
  16. data/lib/idlc-sdk-pfm/command/base.rb +195 -0
  17. data/lib/idlc-sdk-pfm/command/build.rb +120 -0
  18. data/lib/idlc-sdk-pfm/command/configure.rb +41 -0
  19. data/lib/idlc-sdk-pfm/command/destroy.rb +61 -0
  20. data/lib/idlc-sdk-pfm/command/exec.rb +24 -0
  21. data/lib/idlc-sdk-pfm/command/format.rb +64 -0
  22. data/lib/idlc-sdk-pfm/command/generate.rb +83 -0
  23. data/lib/idlc-sdk-pfm/command/generator_commands/base.rb +50 -0
  24. data/lib/idlc-sdk-pfm/command/generator_commands/server_build.rb +58 -0
  25. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/Berksfile +3 -0
  26. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/build_cookbook/.kitchen.yml +21 -0
  27. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/build_cookbook/README.md +146 -0
  28. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/build_cookbook/test-fixture-recipe.rb +8 -0
  29. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/chefignore +107 -0
  30. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/cookbook_readmes/README-policy.md +9 -0
  31. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/cookbook_readmes/README.md +54 -0
  32. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/delivery-config.json +12 -0
  33. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/delivery-project.toml +36 -0
  34. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/gitignore +21 -0
  35. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/README.md +24 -0
  36. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/cookbooks/example/README.md +27 -0
  37. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/cookbooks/example/attributes/default.rb +7 -0
  38. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/cookbooks/example/metadata.rb +6 -0
  39. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/cookbooks/example/recipes/default.rb +8 -0
  40. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/data_bags/README.md +56 -0
  41. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/data_bags/example/example_item.json +4 -0
  42. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/dot-chef-repo.txt +6 -0
  43. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/environments/README.md +9 -0
  44. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/environments/example.json +13 -0
  45. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/policies/README.md +24 -0
  46. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/roles/README.md +9 -0
  47. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/roles/example.json +13 -0
  48. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/spec_helper.rb +2 -0
  49. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/spec_helper_policyfile.rb +2 -0
  50. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/metadata.rb +7 -0
  51. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/app.rb +89 -0
  52. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/attribute.rb +12 -0
  53. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/build_cookbook.rb +182 -0
  54. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/cookbook.rb +144 -0
  55. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/cookbook_file.rb +24 -0
  56. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/lwrp.rb +23 -0
  57. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/policyfile.rb +8 -0
  58. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/recipe.rb +51 -0
  59. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/repo.rb +67 -0
  60. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/template.rb +32 -0
  61. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.all_rights.erb +3 -0
  62. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.apachev2.erb +201 -0
  63. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.gplv2.erb +339 -0
  64. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.gplv3.erb +674 -0
  65. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.mit.erb +21 -0
  66. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/Policyfile.rb.erb +25 -0
  67. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/README.md.erb +4 -0
  68. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/attribute.rb.erb +0 -0
  69. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/build_cookbook/Berksfile.erb +7 -0
  70. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/build_cookbook/metadata.rb.erb +10 -0
  71. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/build_cookbook/recipe.rb.erb +8 -0
  72. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/cookbook_file.erb +0 -0
  73. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/inspec_default_test.rb.erb +18 -0
  74. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/kitchen.yml.erb +26 -0
  75. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/kitchen_policyfile.yml.erb +33 -0
  76. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/metadata.rb.erb +20 -0
  77. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/provider.rb.erb +0 -0
  78. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/recipe.rb.erb +5 -0
  79. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/recipe_spec.rb.erb +22 -0
  80. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/repo/gitignore.erb +128 -0
  81. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/resource.rb.erb +0 -0
  82. data/lib/idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/template.erb +0 -0
  83. data/lib/idlc-sdk-pfm/command/generator_commands.rb +34 -0
  84. data/lib/idlc-sdk-pfm/command/plan.rb +80 -0
  85. data/lib/idlc-sdk-pfm/command/templates/app/files/config/client.rb.template +9 -0
  86. data/lib/idlc-sdk-pfm/command/templates/app/files/config/init.ps1.userdata +16 -0
  87. data/lib/idlc-sdk-pfm/command/templates/base/files/config/client.rb.template +6 -0
  88. data/lib/idlc-sdk-pfm/command/templates/base/files/config/init.ps1.userdata +219 -0
  89. data/lib/idlc-sdk-pfm/command/validate.rb +85 -0
  90. data/lib/idlc-sdk-pfm/command/validator_commands/base.rb +65 -0
  91. data/lib/idlc-sdk-pfm/command/validator_commands/infrastructure.rb +46 -0
  92. data/lib/idlc-sdk-pfm/command/validator_commands/server_build.rb +135 -0
  93. data/lib/idlc-sdk-pfm/command/validator_commands.rb +32 -0
  94. data/lib/idlc-sdk-pfm/commands_map.rb +61 -0
  95. data/lib/idlc-sdk-pfm/generator.rb +52 -0
  96. data/lib/idlc-sdk-pfm/helpers.rb +49 -0
  97. data/lib/idlc-sdk-pfm/settings.rb +205 -0
  98. data/lib/idlc-sdk-pfm/validator.rb +52 -0
  99. data/lib/idlc-sdk-pfm/version.rb +3 -0
  100. data/lib/idlc-sdk-pfm.rb +24 -0
  101. metadata +342 -0
@@ -0,0 +1,195 @@
1
+ require 'mixlib/cli'
2
+ require 'idlc-sdk-pfm/helpers'
3
+
4
+ module Pfm
5
+ module Command
6
+ class Base
7
+ include Mixlib::CLI
8
+ include Pfm::Helpers
9
+
10
+ class InvalidRepository < StandardError; end
11
+ class BuildFailure < StandardError; end
12
+ class DeploymentFailure < StandardError; end
13
+
14
+ option :help,
15
+ short: '-h',
16
+ long: '--help',
17
+ description: 'Show this message',
18
+ boolean: true
19
+
20
+ option :version,
21
+ short: '-v',
22
+ long: '--version',
23
+ description: 'Show pfm version',
24
+ boolean: true
25
+
26
+ option :verbose,
27
+ short: '-V',
28
+ long: '--verbose',
29
+ description: 'Show detailed output',
30
+ boolean: true,
31
+ default: false
32
+
33
+ def initialize
34
+ super
35
+
36
+ @workspace = Idlc::Workspace.new
37
+ end
38
+
39
+ #
40
+ # optparser overwrites -h / --help options with its own.
41
+ # In order to control this behavior, make sure the default options are
42
+ # handled here.
43
+ #
44
+ def run_with_default_options(params = [])
45
+ if needs_help?(params)
46
+ msg(opt_parser.to_s)
47
+ 0
48
+ elsif needs_version?(params)
49
+ msg("Pfm Version: #{Pfm::VERSION}")
50
+ 0
51
+ else
52
+ ENV['DEBUG'] = 'true' if verbose?(params)
53
+ run(params)
54
+ end
55
+ rescue NameError => e
56
+ err("ERROR: #{e.message}\n")
57
+ 1
58
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
59
+ err("ERROR: #{e.message}\n")
60
+ msg(opt_parser)
61
+ 1
62
+ rescue Idlc::Build::MissingMetadataFile, Idlc::Build::MissingRequiredMetadataAttribute, InvalidRepository => e
63
+ err("ERROR: #{e.message}\n")
64
+ 1
65
+ ensure
66
+ @workspace.cleanup unless @workspace.empty?
67
+ end
68
+
69
+ def build_setup
70
+ Packer::Binary.configure do |config|
71
+ config.version = SETTINGS['PACKER_VERSION']
72
+ end
73
+
74
+ @build_config = Idlc::Build::Config.new(SETTINGS['AWS_REGION'])
75
+ @workspace.add(build_base_dir)
76
+
77
+ build_dir = "#{@workspace.tmp_dir}/#{build_base_dir}".freeze
78
+
79
+ msg("Using build template: Build::#{@params.first}::#{@config[:build_template]}::#{@config[:build_metadata]}")
80
+
81
+ # Include build metadata
82
+ @build_metadata = Idlc::Build::Metadata.new(@params.first, @config[:build_metadata])
83
+
84
+ # load the rest of the metadata
85
+ @build_metadata.load
86
+
87
+ # load version from command line if specified
88
+ @build_metadata.attributes['version'] = Idlc::Build::Metadata::MetadataAttribute.new(@config[:build_version], true) unless @config[:build_version].nil?
89
+
90
+ # check metadata requirements
91
+ @build_metadata.requirements_satisfied?
92
+
93
+ msg("Template Version: #{@build_metadata.attributes['version'].value}")
94
+
95
+ @build_metadata.attributes.each do |key, att|
96
+ # load metadata file as packer user vars
97
+ @build_config.add_build_var_v2(key, att.value)
98
+ end
99
+
100
+ # Copy over the base template and auxillary files for Packer
101
+ tpl = Idlc::Build::Template.new(
102
+ @build_metadata.attributes,
103
+ "#{build_dir}/build.json"
104
+ )
105
+ tpl.write
106
+
107
+ # copy auxiliary files
108
+ system("cp -a #{templates_dir}/files #{build_dir}")
109
+
110
+ Dir.chdir(build_dir)
111
+ end
112
+
113
+ def deploy_setup
114
+ Terraform::Binary.configure do |config|
115
+ config.version = SETTINGS['TERRAFORM_VERSION']
116
+ end
117
+
118
+ raise InvalidRepository, 'This doesn\'t look like a valid infrastructure repository' unless File.directory? "#{inf_base_dir}/tf"
119
+ config = Idlc::Deploy::Config.new(SETTINGS['AWS_REGION'])
120
+
121
+ config.parse("#{inf_base_dir}/env/config/default.yml") if File.exist? "#{inf_base_dir}/env/config/default.yml"
122
+
123
+ if ENV['PROD'] == 'true' || ENV['PROD'] == '1'
124
+ config.parse("#{inf_base_dir}/env/config/prod.yml")
125
+ else
126
+ config.parse("#{inf_base_dir}/env/config/devtest.yml")
127
+ end
128
+
129
+ config.parse("#{inf_base_dir}/env/size/#{ENV['SIZE']}.yml") if File.exist? "#{inf_base_dir}/env/size/#{ENV['SIZE']}.yml"
130
+
131
+ inf_conf_file = 'inf.config.yml'
132
+
133
+ # For unit tests
134
+ inf_conf_file = 'inf.config.example.yml' unless File.exist? inf_conf_file
135
+ config.parse(inf_conf_file)
136
+
137
+ bucket_name = Idlc::Deploy::Config.get_deployment_var('tfstate_bucket')
138
+ sub_bucket = "#{Idlc::Deploy::Config.get_deployment_var('job_code')}"\
139
+ "#{Idlc::Deploy::Config.get_deployment_var('job')}"\
140
+ "-#{Idlc::Deploy::Config.get_deployment_var('env')}".freeze
141
+
142
+ # Pass some ENV vars for Terraform
143
+ Idlc::Deploy::Config.add_deployment_var('environment_key', sub_bucket)
144
+ Idlc::Deploy::Config.add_deployment_var('version', REPO_VERSION)
145
+ Idlc::Deploy::Config.add_deployment_var('major_minor', Idlc::Utility.major_minor(REPO_VERSION))
146
+ Idlc::Deploy::Config.add_deployment_var('major_minor_patch', Idlc::Utility.major_minor_patch(REPO_VERSION))
147
+ Idlc::Deploy::Config.add_deployment_var('build', @config[:server_build])
148
+ Idlc::Deploy::Config.add_deployment_var('app_release', @config[:app_release])
149
+
150
+ config.configure_state(bucket_name, sub_bucket)
151
+
152
+ Idlc::Deploy::Keypair.generate("#{inf_base_dir}/env/kp")
153
+ @workspace.flatten("#{inf_base_dir}/tf", 'tf')
154
+ @workspace.add("#{inf_base_dir}/env/kp")
155
+ @workspace.add('lib/tf/modules')
156
+ end
157
+
158
+ def templates_dir
159
+ "#{__dir__}/templates/#{@build_metadata.attributes['build_stage'].value}"
160
+ end
161
+
162
+ def build_base_dir
163
+ "#{SETTINGS['BUILD_BASE_DIR']}/#{@params.first}"
164
+ end
165
+
166
+ def inf_base_dir
167
+ SETTINGS['INF_BASE_DIR']
168
+ end
169
+
170
+ def build_dir
171
+ "#{@workspace.tmp_dir}/#{build_base_dir}".freeze
172
+ end
173
+
174
+ def build_exists?
175
+ return true if Dir.exist? build_base_dir
176
+
177
+ # doesn't exist
178
+ @errors.push("Build::#{@params.first} doesnt exist")
179
+ false
180
+ end
181
+
182
+ def needs_help?(params)
183
+ params.include?('-h') || params.include?('--help')
184
+ end
185
+
186
+ def needs_version?(params)
187
+ params.include?('-v') || params.include?('--version')
188
+ end
189
+
190
+ def verbose?(params)
191
+ params.include?('-V') || params.include?('--verbose')
192
+ end
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,120 @@
1
+ require 'idlc-sdk-pfm/command/base'
2
+ require 'mixlib/shellout'
3
+
4
+ module Pfm
5
+ module Command
6
+ class Build < Base
7
+ banner 'Usage: pfm build BUILD_NAME [options]'
8
+
9
+ option :app_release,
10
+ short: '-a VERSION',
11
+ long: '--app-release VERSION',
12
+ description: 'Application Version Number to build',
13
+ default: ''
14
+
15
+ option :build_version,
16
+ short: '-b VERSION',
17
+ long: '--build-version VERSION',
18
+ description: 'override version number of build',
19
+ default: nil
20
+
21
+ option :build_template,
22
+ short: '-t TEMPLATE',
23
+ long: '--build-template TEMPLATE',
24
+ description: 'The Build Template to use. Defaults to build.json',
25
+ default: 'build.json'
26
+
27
+ option :build_metadata,
28
+ short: '-m METADATA_FILE',
29
+ long: '--build-metadata METADATA_FILE',
30
+ description: 'The build metadata file to use. Defaults to \'metadata\'',
31
+ default: 'metadata'
32
+
33
+ option :build_number,
34
+ short: '-n NUMBER',
35
+ long: '--build-number NUMBER',
36
+ description: 'Override the build number. Default is ENV::BUILD_NUMBER',
37
+ default: ENV['BUILD_NUMBER']
38
+
39
+ def initialize
40
+ super
41
+ @params_valid = true
42
+ @errors = []
43
+ end
44
+
45
+ def run(params)
46
+ @params = params
47
+ read_and_validate_params
48
+
49
+ if params_valid?
50
+ build_setup
51
+ build
52
+ # @workspace.cleanup causing bundler issues
53
+ 0
54
+ else
55
+ @errors.each { |error| err("Error: #{error}") }
56
+ parse_options(params)
57
+ msg(opt_parser)
58
+ 1
59
+ end
60
+ rescue BuildFailure => e
61
+ err("ERROR: #{e.message}\n")
62
+ 1
63
+ end
64
+
65
+ def build
66
+ # Zip the cookbooks for transfer
67
+ Idlc::Workspace.zip_folder('./chef', "#{@workspace.tmp_dir}/cookbooks.zip")
68
+
69
+ # Start the HTTP server to facilitate file transfers. This is to replace
70
+ # WINRM for file transfers in Packer due to slowness. This function returns
71
+ # the process id of the server instance.
72
+ pid = Idlc::Build::Httpd.start(@workspace.tmp_dir)
73
+
74
+ # #start will return twice when forking the HTTP server off, once for the
75
+ # parent and once for the child. When the child return, the pid is nil. We want
76
+ # to skip that run.
77
+ unless pid.nil?
78
+ # Pass some ENV vars for Packer
79
+ @build_config.add_build_var_v2('aws_region', SETTINGS['AWS_REGION'])
80
+ @build_config.add_build_var_v2('app_release', @config[:app_release])
81
+ @build_config.add_build_var_v2('build_uuid', SecureRandom.uuid.to_s)
82
+ @build_config.add_build_var_v2('build_number', @config[:build_number])
83
+ @build_config.add_build_var_v2('httpd_server', Idlc::Build::Httpd.private_ip.to_s)
84
+ @build_config.add_build_var_v2('httpd_port', ENV['HTTPD_PORT'])
85
+
86
+ begin
87
+ Packer::Binary.build("#{@build_config.dump_build_vars} #{@config[:build_template]}")
88
+ Idlc::Build::Httpd.stop(pid)
89
+ Dir.chdir(build_base_dir)
90
+ rescue
91
+ Idlc::Build::Httpd.stop(pid)
92
+ Dir.chdir(build_base_dir)
93
+ raise BuildFailure, 'The build finished with errors'
94
+ end
95
+
96
+ end
97
+
98
+ Dir.chdir(build_base_dir)
99
+ end
100
+
101
+ def read_and_validate_params
102
+ arguments = parse_options(@params)
103
+
104
+ case arguments.size
105
+ when 1
106
+ @params_valid = build_exists?
107
+
108
+ when 2
109
+
110
+ else
111
+ @params_valid = false
112
+ end
113
+ end
114
+
115
+ def params_valid?
116
+ @params_valid
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,41 @@
1
+ require 'idlc-sdk-pfm/command/base'
2
+ require 'mixlib/shellout'
3
+
4
+ module Pfm
5
+ module Command
6
+ class Configure < Pfm::Command::Base
7
+ banner 'Usage: pfm configure SYSTEM_COMMAND'
8
+
9
+ def run(params)
10
+ current_set = Pfm::Settings.new
11
+ new_settings = {}
12
+
13
+ current_set.settings.each do |key, setting|
14
+ print("#{key} [#{setting.value}]: ")
15
+ stdin = STDIN.gets.chomp.strip
16
+
17
+ required = setting.required?
18
+ new_value = setting.value
19
+ new_value = stdin unless null?(stdin)
20
+
21
+ new_settings[key] = Pfm::Settings::Setting.new(new_value, required)
22
+ end
23
+
24
+ current_set.save_config(new_settings)
25
+ end
26
+
27
+ def needs_version?(_params)
28
+ # Force version to get passed down to command
29
+ false
30
+ end
31
+
32
+ def null?(value)
33
+ value.nil? || value == ''
34
+ end
35
+
36
+ def needs_help?(params)
37
+ ['-h', '--help'].include? params[0]
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,61 @@
1
+ require 'idlc-sdk-pfm/command/base'
2
+ require 'mixlib/shellout'
3
+
4
+ module Pfm
5
+ module Command
6
+ class Destroy < Base
7
+ banner 'Usage: pfm destroy [options]'
8
+
9
+ def initialize
10
+ super
11
+ @params_valid = true
12
+ @errors = []
13
+ end
14
+
15
+ def run(params)
16
+ @params = params
17
+ read_and_validate_params
18
+
19
+ if params_valid?
20
+ deploy_setup
21
+ destroy
22
+ # @workspace.cleanup causing bundler issues
23
+ 0
24
+ else
25
+ @errors.each { |error| err("Error: #{error}") }
26
+ parse_options(params)
27
+ msg(opt_parser)
28
+ 1
29
+ end
30
+ rescue DeploymentFailure => e
31
+ err("ERROR: #{e.message}\n")
32
+ 1
33
+ end
34
+
35
+ def destroy
36
+ Idlc::Deploy::Config.add_deployment_var('build', 'null')
37
+ Idlc::Deploy::Config.add_deployment_var('app_release', 'null')
38
+
39
+ Terraform::Binary.get("-update #{@workspace.tmp_dir}")
40
+ Terraform::Binary.destroy("-refresh=false #{@workspace.tmp_dir}")
41
+ rescue
42
+ raise DeploymentFailure, 'Finished with errors'
43
+ end
44
+
45
+ def read_and_validate_params
46
+ arguments = parse_options(@params)
47
+
48
+ @params_valid = case arguments.size
49
+ when 0
50
+ true
51
+ else
52
+ false
53
+ end
54
+ end
55
+
56
+ def params_valid?
57
+ @params_valid
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,24 @@
1
+ require 'idlc-sdk-pfm/command/base'
2
+ require 'mixlib/shellout'
3
+
4
+ module Pfm
5
+ module Command
6
+ class Exec < Pfm::Command::Base
7
+ banner 'Usage: pfm exec SYSTEM_COMMAND'
8
+
9
+ def run(params)
10
+ exec(*params)
11
+ raise 'Exec failed without an exception, your ruby is buggy' # should never get here
12
+ end
13
+
14
+ def needs_version?(_params)
15
+ # Force version to get passed down to command
16
+ false
17
+ end
18
+
19
+ def needs_help?(params)
20
+ ['-h', '--help'].include? params[0]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,64 @@
1
+ require 'idlc-sdk-pfm/command/base'
2
+ require 'mixlib/shellout'
3
+
4
+ module Pfm
5
+ module Command
6
+ class Format < Base
7
+ banner 'Usage: pfm format [options]'
8
+
9
+ def initialize
10
+ super
11
+ @params_valid = true
12
+ @errors = []
13
+ end
14
+
15
+ def run(params)
16
+ @params = params
17
+ read_and_validate_params
18
+
19
+ if params_valid?
20
+ fmt
21
+ # @workspace.cleanup causing bundler issues
22
+ 0
23
+ else
24
+ @errors.each { |error| err("Error: #{error}") }
25
+ parse_options(params)
26
+ msg(opt_parser)
27
+ 1
28
+ end
29
+ rescue DeploymentFailure => e
30
+ err("ERROR: #{e.message}\n")
31
+ 1
32
+ end
33
+
34
+ def fmt
35
+ raise InvalidRepository, 'This doesn\'t look like a valid infrastructure repository' unless File.directory? "#{inf_base_dir}/tf"
36
+ tf_paths = %W[#{inf_base_dir}/tf lib/tf/modules]
37
+
38
+ begin
39
+ tf_paths.each do |path|
40
+ # Format the file to a canonical syntax
41
+ Terraform::Binary.fmt(path)
42
+ end
43
+ rescue
44
+ raise DeploymentFailure, 'Finished with errors'
45
+ end
46
+ end
47
+
48
+ def read_and_validate_params
49
+ arguments = parse_options(@params)
50
+
51
+ case arguments.size
52
+ when 0
53
+ @params_valid = true
54
+ else
55
+ @params_valid = false
56
+ end
57
+ end
58
+
59
+ def params_valid?
60
+ @params_valid
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,83 @@
1
+ require 'idlc-sdk-pfm/command/base'
2
+ require 'idlc-sdk-pfm/command/generator_commands'
3
+ require 'idlc-sdk-pfm/command/generator_commands/base'
4
+ require 'idlc-sdk-pfm/command/generator_commands/server_build'
5
+
6
+ module Pfm
7
+ module Command
8
+ class Generate < Base
9
+
10
+ GeneratorCommand = Struct.new(:name, :class_name, :description)
11
+
12
+ def self.generators
13
+ @generators ||= []
14
+ end
15
+
16
+ def self.generator(name, class_name, description)
17
+ generators << GeneratorCommand.new(name, class_name, description)
18
+ end
19
+
20
+ generator('server-build', :ServerBuild, 'Generate a server build repo')
21
+
22
+ def self.banner_headline
23
+ <<-E
24
+ Usage: pfm generate GENERATOR [options]
25
+ Available generators:
26
+ E
27
+ end
28
+
29
+ def self.generator_list
30
+ justify_size = generators.map { |g| g.name.size }.max + 2
31
+ generators.map { |g| " #{g.name.to_s.ljust(justify_size)}#{g.description}" }.join("\n")
32
+ end
33
+
34
+ def self.banner
35
+ banner_headline + generator_list + "\n"
36
+ end
37
+
38
+ # pfm generate app path/to/basename --skel=path/to/skeleton --example
39
+ # pfm generate file name [path/to/cookbook_root] (inferred from cwd) --from=source_file
40
+
41
+ def initialize(*args)
42
+ super
43
+ end
44
+
45
+ def run(params)
46
+ if generator_spec = generator_for(params[0])
47
+ params.shift
48
+ generator = GeneratorCommands.build(generator_spec.class_name, params)
49
+ generator.run
50
+ else
51
+ msg(banner)
52
+ 1
53
+ end
54
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
55
+ # Pfm::Command::Base also handles this error in the same way, but it
56
+ # does not have access to the correct option parser, so it cannot print
57
+ # the usage correctly. Therefore, invalid CLI usage needs to be handled
58
+ # here.
59
+ err("ERROR: #{e.message}\n")
60
+ msg(generator.opt_parser)
61
+ 1
62
+ end
63
+
64
+ def generator_for(arg)
65
+ self.class.generators.find { |g| g.name.to_s == arg }
66
+ end
67
+
68
+ # In the Base class, this is defined to be true if any args match "-h" or
69
+ # "--help". Here we override that behavior such that if the first
70
+ # argument is a valid generator name, like `pfm generate cookbook -h`,
71
+ # we delegate the request to the specified generator.
72
+ def needs_help?(params)
73
+ return false if have_generator?(params[0])
74
+ super
75
+ end
76
+
77
+ def have_generator?(name)
78
+ self.class.generators.map { |g| g.name.to_s }.include?(name)
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,50 @@
1
+ require "idlc-sdk-pfm/command/generator_commands"
2
+
3
+ module Pfm
4
+ module Command
5
+ module GeneratorCommands
6
+ # ## Base
7
+ #
8
+ # Base class for `chef generate` subcommands. Contains basic behaviors
9
+ # for setting up the generator context, detecting git, and launching a
10
+ # chef converge.
11
+ #
12
+ # The behavior of the generators is largely delegated to a chef cookbook.
13
+ # The default implementation is the `code_generator` cookbook in
14
+ # pfm/skeletons/code_generator.
15
+ class Base < Command::Base
16
+
17
+ attr_reader :params
18
+ attr_reader :errors
19
+
20
+ options.merge!(SharedGeneratorOptions.options)
21
+
22
+ def initialize(params)
23
+ super()
24
+ @params_valid = true
25
+ @errors = []
26
+ @params = params
27
+ end
28
+
29
+ def setup_context
30
+ end
31
+
32
+ def read_and_validate_params
33
+ arguments = parse_options(params)
34
+ case arguments.size
35
+ when 1
36
+
37
+ when 2
38
+
39
+ else
40
+ @params_valid = false
41
+ end
42
+ end
43
+
44
+ def params_valid?
45
+ @params_valid
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,58 @@
1
+ module Pfm
2
+ module Command
3
+ module GeneratorCommands
4
+ class ServerBuild < Base
5
+ banner 'Usage: pfm generate server-build NAME [options]'
6
+
7
+ options.merge!(SharedGeneratorOptions.options)
8
+
9
+ def run
10
+ read_and_validate_params
11
+ if params_valid?
12
+ setup_context
13
+
14
+ mk_build_dirs
15
+ default_build_files
16
+ default_cookbooks
17
+ else
18
+ errors.each { |error| err("Error: #{error}") }
19
+ parse_options(params)
20
+ msg(opt_parser)
21
+ 1
22
+ end
23
+ end
24
+
25
+ def mk_build_dirs
26
+ %w(
27
+ chef/bake/cookbooks
28
+ chef/fry/cookbooks
29
+ chef/vendor/cookbooks
30
+ ).each do |path|
31
+ FileUtils.mkdir_p("#{base_dir}/#{path}", verbose: verbose?(params))
32
+ end
33
+ end
34
+
35
+ def default_build_files
36
+ %w(
37
+ metadata
38
+ ).each do |file|
39
+ FileUtils.touch("#{base_dir}/#{file}", verbose: verbose?(params))
40
+ end
41
+ end
42
+
43
+ def default_cookbooks
44
+ %w(
45
+ chef/bake/cookbooks/bake
46
+ chef/fry/cookbooks/fry
47
+ ).each do |cookbook|
48
+ system("chef generate cookbook #{base_dir}/#{cookbook} -g #{__dir__}/skeletons/code_generator")
49
+ end
50
+ end
51
+
52
+ def base_dir
53
+ "builds/#{@params.first}"
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ source 'https://supermarket.chef.io'
2
+
3
+ metadata