bosh-gen 0.16.2 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +13 -5
  2. data/.rspec +3 -0
  3. data/.travis.yml +16 -0
  4. data/ChangeLog.md +110 -89
  5. data/Gemfile +7 -1
  6. data/Guardfile +4 -8
  7. data/README.md +52 -22
  8. data/Rakefile +10 -0
  9. data/bosh-gen.gemspec +7 -5
  10. data/lib/bosh/gen/cli.rb +20 -28
  11. data/lib/bosh/gen/generators/job_generator.rb +9 -10
  12. data/lib/bosh/gen/generators/job_generator/templates/jobs/%job_name%_simple/templates/bin/%job_name%_ctl.tt +5 -5
  13. data/lib/bosh/gen/generators/new_release_generator.rb +63 -68
  14. data/lib/bosh/gen/generators/new_release_generator/templates/jobs/%project_name_hyphenated%/templates/bin/%job_name%_ctl.tt +5 -5
  15. data/lib/bosh/gen/generators/new_release_generator/templates/jobs/%project_name_hyphenated%/templates/data/properties.sh.erb +6 -0
  16. data/lib/bosh/gen/generators/new_release_generator/templates/templates/infrastructure-aws-ec2.yml.tt +7 -5
  17. data/lib/bosh/gen/generators/new_release_generator/templates/templates/infrastructure-warden.yml.tt +3 -4
  18. data/lib/bosh/gen/generators/new_release_generator/templates/templates/jobs.yml.tt +3 -0
  19. data/lib/bosh/gen/generators/new_release_generator/templates/templates/make_manifest.tt +18 -2
  20. data/lib/bosh/gen/generators/new_release_generator/templates/templates/stub.yml.tt +2 -1
  21. data/lib/bosh/gen/settings.rb +61 -0
  22. data/lib/bosh/gen/version.rb +1 -1
  23. data/spec/fixtures/deployment_manifests/2_jobs_1_ip_8196_disk_with_numeric.yml +64 -0
  24. data/spec/fixtures/releases/s3test-boshrelease/.gitignore +18 -0
  25. data/spec/fixtures/releases/s3test-boshrelease/README.md +51 -0
  26. data/spec/fixtures/releases/s3test-boshrelease/Rakefile +15 -0
  27. data/spec/fixtures/releases/s3test-boshrelease/config/blobs.yml +1 -0
  28. data/spec/fixtures/releases/s3test-boshrelease/config/final.yml +5 -0
  29. data/spec/fixtures/releases/s3test-boshrelease/jobs/.gitkeep +0 -0
  30. data/spec/fixtures/releases/s3test-boshrelease/jobs/s3test/monit +5 -0
  31. data/spec/fixtures/releases/s3test-boshrelease/jobs/s3test/spec +13 -0
  32. data/spec/fixtures/releases/s3test-boshrelease/jobs/s3test/templates/bin/monit_debugger +13 -0
  33. data/spec/fixtures/releases/s3test-boshrelease/jobs/s3test/templates/bin/s3test_ctl +36 -0
  34. data/spec/fixtures/releases/s3test-boshrelease/jobs/s3test/templates/config/.gitkeep +0 -0
  35. data/spec/fixtures/releases/s3test-boshrelease/jobs/s3test/templates/config/s3test.conf.erb +5 -0
  36. data/spec/fixtures/releases/s3test-boshrelease/jobs/s3test/templates/data/properties.sh.erb +10 -0
  37. data/spec/fixtures/releases/s3test-boshrelease/jobs/s3test/templates/helpers/ctl_setup.sh +81 -0
  38. data/spec/fixtures/releases/s3test-boshrelease/jobs/s3test/templates/helpers/ctl_utils.sh +156 -0
  39. data/spec/fixtures/releases/s3test-boshrelease/packages/.gitkeep +0 -0
  40. data/spec/fixtures/releases/s3test-boshrelease/src/.gitkeep +0 -0
  41. data/spec/fixtures/releases/s3test-boshrelease/templates/deployment.yml +35 -0
  42. data/spec/fixtures/releases/s3test-boshrelease/templates/infrastructure-aws-ec2.yml +40 -0
  43. data/spec/fixtures/releases/s3test-boshrelease/templates/infrastructure-warden.yml +107 -0
  44. data/spec/fixtures/releases/s3test-boshrelease/templates/jobs.yml +30 -0
  45. data/spec/fixtures/releases/s3test-boshrelease/templates/make_manifest +54 -0
  46. data/spec/fixtures/releases/s3test-boshrelease/templates/stub.yml +13 -0
  47. data/spec/generators/deployment_manifest_generator_spec.rb +19 -14
  48. data/spec/generators/{jobs/webapp_job_generator_spec.rb → job_generator_spec.rb} +8 -13
  49. data/spec/generators/new_release_generator_spec.rb +70 -0
  50. data/spec/models/bosh_config_spec.rb +3 -3
  51. data/spec/models/deployment_manifest_spec.rb +16 -6
  52. data/spec/models/release_detection_spec.rb +6 -6
  53. data/spec/spec_helper.rb +27 -7
  54. data/spec/support/fog.rb +3 -0
  55. data/spec/{generators → support}/generator_spec_helper.rb +47 -6
  56. metadata +105 -36
  57. data/spec/models/extract_spec.rb +0 -10
data/Rakefile CHANGED
@@ -1,3 +1,13 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
3
 
4
+ require "rspec/core/rake_task"
5
+
6
+
7
+ desc "Run Tests"
8
+ RSpec::Core::RakeTask.new(:spec) do |t|
9
+ t.pattern = "spec/unit/**/*_spec.rb"
10
+ t.rspec_opts = %w(--format progress --color)
11
+ end
12
+
13
+ task :default => :spec
data/bosh-gen.gemspec CHANGED
@@ -14,13 +14,15 @@ Gem::Specification.new do |gem|
14
14
  gem.name = "bosh-gen"
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = Bosh::Gen::VERSION
17
-
17
+
18
18
  gem.add_dependency "thor"
19
19
  gem.add_dependency "bosh_cli"
20
20
  gem.add_dependency "bosh_common"
21
-
21
+
22
+ gem.add_dependency "cyoi", "~> 0.10.0"
23
+ gem.add_dependency "fog", "~> 1.11"
24
+ gem.add_dependency "readwritesettings", "~> 3.0"
25
+
22
26
  gem.add_development_dependency "rake"
23
- gem.add_development_dependency "minitest", "~> 2.12"
24
- gem.add_development_dependency "minitest-colorize"
25
- gem.add_development_dependency "guard-minitest"
27
+ gem.add_development_dependency "rspec-fire"
26
28
  end
data/lib/bosh/gen/cli.rb CHANGED
@@ -2,7 +2,7 @@ require "thor"
2
2
 
3
3
  # bosh_cli libraries
4
4
  module Bosh; end
5
- require "cli/config"
5
+ require "cli/config"
6
6
  require "cli/core_ext"
7
7
 
8
8
  require 'bosh/gen/models'
@@ -11,27 +11,19 @@ module Bosh
11
11
  module Gen
12
12
  class Command < Thor
13
13
  include Thor::Actions
14
-
14
+
15
15
  desc "new PATH", "Creates a new BOSH release"
16
- method_option :s3, :alias => ["--aws"], :type => :boolean,
17
- :desc => "Use AWS S3 bucket for blobstore"
18
- method_option :atmos, :type => :boolean,
19
- :desc => "Use EMC ATMOS for blobstore"
20
- method_option :swift, :type => :boolean,
21
- :desc => "Use OpenStack Swift for blobstore"
22
16
  def new(path)
23
- flags = { :aws => options["s3"], :atmos => options["atmos"],
24
- :swift => options["swift"]}
25
17
  require 'bosh/gen/generators/new_release_generator'
26
- Bosh::Gen::Generators::NewReleaseGenerator.start([path, flags])
18
+ Bosh::Gen::Generators::NewReleaseGenerator.start([path])
27
19
  end
28
-
20
+
29
21
  desc "package NAME", "Create a new package"
30
- method_option :apt, :type => :boolean,
22
+ method_option :apt, :type => :boolean,
31
23
  :desc => "Create package using debian/ubuntu apt .debs"
32
- method_option :dependencies, :aliases => ['-d'], :type => :array,
24
+ method_option :dependencies, :aliases => ['-d'], :type => :array,
33
25
  :desc => "List of package dependencies"
34
- method_option :files, :aliases => ['-f'], :type => :array,
26
+ method_option :files, :aliases => ['-f'], :type => :array,
35
27
  :desc => "List of files copy into release"
36
28
  method_option :src, :aliases => ['-s'], :type => :array,
37
29
  :desc => "List of existing sources to use, e.g. --src 'myapp/**/*'"
@@ -48,9 +40,9 @@ module Bosh
48
40
  [name, dependencies, files, sources])
49
41
  end
50
42
  end
51
-
43
+
52
44
  desc "source NAME", "Downloads a source item into the named project"
53
- method_option :blob, :aliases => ['-b'], :type => :boolean,
45
+ method_option :blob, :aliases => ['-b'], :type => :boolean,
54
46
  :desc => "Store file in blobstore"
55
47
  def source(name, uri)
56
48
  flags = { :blob => options[:blob] || false }
@@ -70,9 +62,9 @@ module Bosh
70
62
  Bosh::Gen::Generators::PackageSourceGenerator.start(
71
63
  [name, files, flags])
72
64
  end
73
-
65
+
74
66
  desc "job NAME", "Create a new job"
75
- method_option :dependencies, :aliases => ['-d'], :type => :array,
67
+ method_option :dependencies, :aliases => ['-d'], :type => :array,
76
68
  :desc => "List of package dependencies"
77
69
  def job(name)
78
70
  dependencies = options[:dependencies] || []
@@ -81,7 +73,7 @@ module Bosh
81
73
  end
82
74
 
83
75
  desc "micro [JOB]", "Create a micro job - a collection of all jobs and packages"
84
- method_option :jobs, :aliases => ['-j'], :type => :array,
76
+ method_option :jobs, :aliases => ['-j'], :type => :array,
85
77
  :desc => "Ordered list of jobs to include"
86
78
  def micro(job_name = "micro")
87
79
  specific_jobs = options[:jobs] || []
@@ -89,14 +81,14 @@ module Bosh
89
81
  Bosh::Gen::Generators::MicroJobGenerator.start([job_name, specific_jobs])
90
82
  end
91
83
 
92
- desc "template JOB FILE_PATH",
84
+ desc "template JOB FILE_PATH",
93
85
  "Add a Job template (example FILE_PATH: config/httpd.conf)"
94
86
  def template(job_name, file_path)
95
87
  require 'bosh/gen/generators/job_template_generator'
96
88
  Bosh::Gen::Generators::JobTemplateGenerator.start([job_name, file_path])
97
89
  end
98
-
99
- desc "extract-job SOURCE_PACKAGE_PATH",
90
+
91
+ desc "extract-job SOURCE_PACKAGE_PATH",
100
92
  "Extracts a job from another release and all its " +
101
93
  "dependent packages and source"
102
94
  def extract_job(source_package_path)
@@ -105,7 +97,7 @@ module Bosh
105
97
  Bosh::Gen::Generators::ExtractJobGenerator.start([source_package_path])
106
98
  end
107
99
 
108
- desc "extract-pkg SOURCE_PACKAGE_PATH",
100
+ desc "extract-pkg SOURCE_PACKAGE_PATH",
109
101
  "Extracts a package from another release and all its " +
110
102
  "dependent packages and sources"
111
103
  def extract_pkg(source_package_path)
@@ -114,13 +106,13 @@ module Bosh
114
106
  Bosh::Gen::Generators::ExtractPackageGenerator.start([source_package_path])
115
107
  end
116
108
 
117
- desc "manifest NAME PATH",
109
+ desc "manifest NAME PATH",
118
110
  "Creates a deployment manifest based on the release located at PATH"
119
- method_option :force, :type => :boolean,
111
+ method_option :force, :type => :boolean,
120
112
  :desc => "Force override existing target manifest file"
121
- method_option :addresses, :aliases => ['-a'], :type => :array,
113
+ method_option :addresses, :aliases => ['-a'], :type => :array,
122
114
  :desc => "List of IP addresses available for jobs"
123
- method_option :disk, :aliases => ['-d'], :type => :string,
115
+ method_option :disk, :aliases => ['-d'], :type => :string,
124
116
  :desc => "Attach persistent disks to VMs of specific size, e.g. 8196"
125
117
  method_option :jobs, :type => :array,
126
118
  :desc => "Specific jobs to include in manifest [default: all]"
@@ -9,17 +9,17 @@ module Bosh::Gen
9
9
  argument :job_name
10
10
  argument :dependencies, :type => :array
11
11
  argument :purpose
12
-
12
+
13
13
  def self.source_root
14
14
  File.join(File.dirname(__FILE__), "job_generator", "templates")
15
15
  end
16
-
16
+
17
17
  def check_root_is_release
18
18
  unless File.exist?("jobs") && File.exist?("packages")
19
19
  raise Thor::Error.new("run inside a BOSH release project")
20
20
  end
21
21
  end
22
-
22
+
23
23
  def check_name
24
24
  raise Thor::Error.new("'#{job_name}' is not a valid BOSH id") unless job_name.bosh_valid_id?
25
25
  end
@@ -38,7 +38,7 @@ module Bosh::Gen
38
38
  end
39
39
  end
40
40
  end
41
-
41
+
42
42
  # copy the thor template files into the bosh release to be bosh templates
43
43
  # that's right, templates (.tt) can become templates (.erb)
44
44
  def template_files
@@ -46,7 +46,6 @@ module Bosh::Gen
46
46
  directory "jobs/%job_name%_#{purpose}", "jobs/#{job_name}"
47
47
 
48
48
  # build a hash of { 'bin/webapp_ctl.erb' => 'bin/webapp_ctl', ...} used in spec
49
- # TODO: do I need to flatten it to { 'webapp_ctl' => 'bin/webapp_ctl' }?
50
49
  @template_files = {}
51
50
  FileUtils.chdir(File.join(generator_job_templates_path, "templates")) do
52
51
  `ls */*`.split("\n").each do |template_file|
@@ -60,25 +59,25 @@ module Bosh::Gen
60
59
  end
61
60
  end
62
61
  end
63
-
62
+
64
63
  def job_specification
65
64
  config = { "name" => job_name, "packages" => dependencies, "templates" => @template_files }
66
65
  create_file job_dir("spec"), YAML.dump(config)
67
66
  end
68
-
67
+
69
68
  private
70
69
  def filenames
71
70
  files.map {|f| File.basename(f) }
72
71
  end
73
-
72
+
74
73
  def job_dir(path)
75
74
  File.join("jobs", job_name, path)
76
75
  end
77
-
76
+
78
77
  def valid_purposes
79
78
  %w[simple]
80
79
  end
81
-
80
+
82
81
  # Run a command in git.
83
82
  #
84
83
  # ==== Examples
@@ -14,13 +14,13 @@ case $1 in
14
14
  start)
15
15
  pid_guard $PIDFILE $JOB_NAME
16
16
 
17
- # TODO: Run some process
18
- exec chpst -u vcap:vcap TODO \
17
+ # store pid in $PIDFILE
18
+ echo $$ > $PIDFILE
19
+
20
+ exec chpst -u vcap:vcap <%= job_name %> \
19
21
  >>$LOG_DIR/$JOB_NAME.stdout.log \
20
22
  2>>$LOG_DIR/$JOB_NAME.stderr.log
21
23
 
22
- # store pid in $PIDFILE
23
- echo $! > $PIDFILE
24
24
  ;;
25
25
 
26
26
  stop)
@@ -33,4 +33,4 @@ case $1 in
33
33
  ;;
34
34
 
35
35
  esac
36
- exit 0
36
+ exit 0
@@ -1,32 +1,42 @@
1
- require 'yaml'
2
- require 'thor/group'
1
+ require "yaml"
2
+ require "thor/group"
3
+ require "cyoi/cli/provider"
4
+ require "cyoi/cli/blobstore"
5
+ require "bosh/gen/settings"
3
6
 
4
7
  module Bosh::Gen
5
8
  module Generators
6
9
  class NewReleaseGenerator < Thor::Group
7
10
  include Thor::Actions
11
+ include Bosh::Gen::Settings
8
12
 
9
13
  argument :proposed_app_path
10
- argument :flags, :type => :hash
11
-
14
+
12
15
  def self.source_root
13
16
  File.join(File.dirname(__FILE__), "new_release_generator", "templates")
14
17
  end
15
-
18
+
16
19
  def create_root
17
20
  self.destination_root = File.expand_path(repository_path, destination_root)
18
21
  empty_directory '.'
19
22
  FileUtils.cd(destination_root) unless options[:pretend]
20
23
  end
21
-
24
+
25
+ def select_provider
26
+ self.settings_dir = File.expand_path("config")
27
+ provider = Cyoi::Cli::Provider.new([settings_dir])
28
+ provider.execute!
29
+ reload_settings!
30
+ end
31
+
22
32
  def readme
23
33
  template "README.md.tt", "README.md"
24
34
  end
25
-
35
+
26
36
  def rakefile
27
37
  copy_file "Rakefile"
28
38
  end
29
-
39
+
30
40
  def directories
31
41
  %w[jobs packages src blobs templates].each do |dir|
32
42
  directory dir
@@ -40,15 +50,16 @@ module Bosh::Gen
40
50
  def blobs_yaml
41
51
  create_file "config/blobs.yml", YAML.dump({})
42
52
  end
43
-
44
- # TODO - support other blobstores
45
- def local_blobstore
53
+
54
+ def config_dev_yml
46
55
  config_dev = { "dev_name" => project_name }
47
56
  create_file "config/dev.yml", YAML.dump(config_dev)
57
+ end
48
58
 
59
+ def config_private_yml
49
60
  case blobstore_type
50
61
  when :local
51
- config_private = {
62
+ config_private = {
52
63
  "blobstore" => {
53
64
  "simple" => {
54
65
  "user" => "USER",
@@ -57,41 +68,28 @@ module Bosh::Gen
57
68
  }
58
69
  }
59
70
  when :s3
60
- config_private = {
71
+ config_private = {
61
72
  "blobstore" => {
62
73
  "s3" => {
63
- "access_key_id" => readwrite_aws_access_key,
64
- "secret_access_key" => readwrite_aws_secret_access_key
65
- }
66
- }
67
- }
68
- when :atmos
69
- config_private = {
70
- "blobstore" => {
71
- "atmos" => {
72
- "secret" => "SECRET"
74
+ "access_key_id" => settings.provider.credentials.aws_access_key_id,
75
+ "secret_access_key" => settings.provider.credentials.aws_secret_access_key
73
76
  }
74
77
  }
75
78
  }
79
+ # https://github.com/cloudfoundry/bosh/tree/master/blobstore_client#openstack-object-storage
76
80
  when :swift
77
81
  config_private = {
78
82
  "blobstore" => {
79
83
  "swift" => {
80
- "rackspace" => {
81
- "rackspace_username" => "USERNAME",
82
- "rackspace_api_key" => "API_KEY"
83
- },
84
- "hp" => {
85
- "hp_account_id" => "ACCESS_KEY_ID",
86
- "hp_secret_key" => "SECRET_KEY",
87
- "hp_tenant_id" => "TENANT_ID"
88
- },
84
+ settings.provider.name => settings.provider.credentials.to_hash
89
85
  }
90
86
  }
91
87
  }
92
88
  end
93
89
  create_file "config/private.yml", YAML.dump(config_private)
90
+ end
94
91
 
92
+ def config_final_yml
95
93
  case blobstore_type
96
94
  when :local
97
95
  say_status "warning", "config/final.yml defaulting to local blobstore /tmp/blobstore", :yellow
@@ -104,20 +102,7 @@ module Bosh::Gen
104
102
  config_final = { "blobstore" => {
105
103
  "provider" => "s3",
106
104
  "options" => {
107
- "bucket_name" => repository_name,
108
- "access_key_id" => readonly_aws_access_key,
109
- "secret_access_key" => readonly_aws_secret_access_key,
110
- "encryption_key" => "PERSONAL_RANDOM_KEY",
111
- }
112
- }
113
- }
114
- when :atmos
115
- config_final = { "blobstore" => {
116
- "provider" => "atmos",
117
- "options" => {
118
- "tag" => repository_name,
119
- "url" => "https://blob.cfblob.com",
120
- "uid" => "ATMOS_UID"
105
+ "bucket_name" => repository_name
121
106
  }
122
107
  }
123
108
  }
@@ -126,19 +111,20 @@ module Bosh::Gen
126
111
  "provider" => "swift",
127
112
  "options" => {
128
113
  "container_name" => repository_name,
129
- "swift_provider" => "SWIFT_PROVIDER"
114
+ "swift_provider" => swift_provider
130
115
  }
131
116
  }
132
117
  }
133
118
  end
134
-
119
+
135
120
  create_file "config/final.yml", YAML.dump(config_final)
136
121
  end
137
-
122
+
138
123
  def git_init
139
124
  create_file ".gitignore", <<-IGNORE.gsub(/^\s{8}/, '')
140
125
  config/dev.yml
141
126
  config/private.yml
127
+ config/settings.yml
142
128
  releases/*.tgz
143
129
  dev_releases
144
130
  blobs/*
@@ -157,7 +143,7 @@ module Bosh::Gen
157
143
  my*.yml
158
144
  IGNORE
159
145
  end
160
-
146
+
161
147
  def setup_git
162
148
  git :init
163
149
  git :add => "."
@@ -170,6 +156,17 @@ module Bosh::Gen
170
156
  say "cd #{repository_path}", :yellow
171
157
  end
172
158
 
159
+ def create_blobstore
160
+ say ""
161
+ say "Finally..."
162
+ blobstore = Cyoi::Cli::Blobstore.new([blobstore_name, settings_dir])
163
+ blobstore.execute!
164
+ reload_settings!
165
+ say ""
166
+ end
167
+
168
+
169
+
173
170
  private
174
171
 
175
172
  # converts the base name into having -boshrelease suffix
@@ -177,6 +174,10 @@ module Bosh::Gen
177
174
  @repository_name ||= "#{project_name}-boshrelease"
178
175
  end
179
176
 
177
+ def blobstore_name
178
+ repository_name
179
+ end
180
+
180
181
  def repository_path
181
182
  File.join(File.dirname(proposed_app_path), repository_name)
182
183
  end
@@ -190,30 +191,31 @@ module Bosh::Gen
190
191
  end
191
192
 
192
193
  def project_name_hyphenated
193
- project_name.gsub(/[^A-Za-z]+/, '-')
194
+ project_name.gsub(/[^A-Za-z0-9]+/, '-')
194
195
  end
195
196
 
196
197
  def project_name_underscored
197
- project_name.gsub(/[^A-Za-z]+/, '_')
198
+ project_name.gsub(/[^A-Za-z0-9]+/, '_')
198
199
  end
199
200
 
200
201
  def blobstore_type
201
202
  return :s3 if s3?
202
- return :atmos if atmos?
203
203
  return :swift if swift?
204
204
  return :local
205
205
  end
206
-
206
+
207
207
  def s3?
208
- flags[:aws]
209
- end
210
-
211
- def atmos?
212
- flags[:atmos]
208
+ settings.provider.name == "aws"
213
209
  end
214
210
 
215
211
  def swift?
216
- flags[:swift]
212
+ settings.provider.name == "openstack"
213
+ end
214
+
215
+ # https://github.com/cloudfoundry/bosh/tree/master/blobstore_client#openstack-swift-provider
216
+ # TODO: supported: hp, openstack and rackspace; How to detect this from fog?
217
+ def swift_provider
218
+ "openstack"
217
219
  end
218
220
 
219
221
  # Run a command in git.
@@ -234,14 +236,6 @@ module Bosh::Gen
234
236
  end
235
237
  end
236
238
 
237
- def readonly_aws_access_key
238
- s3_credentials "readonly_access_key", "READONLY_AWS_ACCESS_KEY"
239
- end
240
-
241
- def readonly_aws_secret_access_key
242
- s3_credentials "readonly_secret_access_key", "READONLY_AWS_SECRET_ACCESS_KEY"
243
- end
244
-
245
239
  def readwrite_aws_access_key
246
240
  s3_credentials "readwrite_access_key", "READWRITE_AWS_ACCESS_KEY"
247
241
  end
@@ -261,6 +255,7 @@ module Bosh::Gen
261
255
  end
262
256
  @s3_credentials[key] || default
263
257
  end
258
+
264
259
  end
265
260
  end
266
261
  end