bosh-gen 0.3.0 → 0.3.2

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.
data/ChangeLog.md CHANGED
@@ -7,6 +7,21 @@ Added:
7
7
  * `template` - add a template/file to a job
8
8
  * `source` - download and add a source file/tarball to a package
9
9
 
10
+ ### v0.3.1 (never released)
11
+
12
+ Added:
13
+
14
+ * `manifest` - generate a deployment manifest for a release
15
+
16
+ Fixed:
17
+
18
+ * `job` - creates a monit script and a stub control script
19
+
20
+ ### v0.3.2
21
+
22
+ * `job` - ctl file has TODO to remind about PID file
23
+ * `job` - use the provided release path to detect jobs
24
+
10
25
  ## v0.2
11
26
 
12
27
  Added:
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'minitest' do
5
+ # with Minitest::Spec
6
+ watch(%r|^spec/(.*)_spec\.rb|)
7
+ watch(%r|^lib/bosh/gen/(.*)([^/]+)\.rb|) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
8
+ watch(%r|^spec/spec_helper\.rb|) { "spec" }
9
+ end
data/Rakefile CHANGED
@@ -1,2 +1,3 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
+
data/bosh-gen.gemspec CHANGED
@@ -19,4 +19,7 @@ Gem::Specification.new do |gem|
19
19
  gem.add_dependency "bosh_cli"
20
20
 
21
21
  gem.add_development_dependency "rake"
22
+ gem.add_development_dependency "minitest", "~> 2.12"
23
+ gem.add_development_dependency "minitest-colorize"
24
+ gem.add_development_dependency "guard-minitest"
22
25
  end
data/lib/bosh/gen/cli.rb CHANGED
@@ -5,6 +5,7 @@ module Bosh; end
5
5
  require "cli/config"
6
6
  require "cli/core_ext"
7
7
 
8
+ require 'bosh/gen/models'
8
9
 
9
10
  module Bosh
10
11
  module Gen
@@ -58,7 +59,18 @@ module Bosh
58
59
  require 'bosh/gen/generators/job_template_generator'
59
60
  Bosh::Gen::Generators::JobTemplateGenerator.start([job_name, file_path])
60
61
  end
61
-
62
+
63
+ desc "manifest NAME PATH", "Creates a deployment manifest based on the release located at PATH"
64
+ method_option :force, :type => :boolean, :desc => "Force override existing target manifest file"
65
+ method_option :addresses, :aliases => ['-a'], :type => :array, :desc => "List of IP addresses available for jobs"
66
+ def manifest(name, release_path)
67
+ release_path = File.expand_path(release_path)
68
+ ip_addresses = options["addresses"] || []
69
+ flags = { :force => options["force"] || false }
70
+ require 'bosh/gen/generators/deployment_manifest_generator'
71
+ Bosh::Gen::Generators::DeploymentManifestGenerator.start([name, release_path, ip_addresses, flags])
72
+ end
73
+
62
74
  no_tasks do
63
75
  def cyan; "\033[36m" end
64
76
  def clear; "\033[0m" end
@@ -0,0 +1,60 @@
1
+ require 'yaml'
2
+ require 'thor/group'
3
+
4
+ module Bosh::Gen
5
+ module Generators
6
+ class DeploymentManifestGenerator < Thor::Group
7
+ include Thor::Actions
8
+
9
+ argument :name
10
+ argument :release_path
11
+ argument :ip_addresses
12
+ argument :flags, :type => :hash
13
+
14
+ def check_release_path_is_release
15
+ unless File.exist?(release_path)
16
+ raise Thor::Error.new("target path '#{release_path}' doesn't exist")
17
+ end
18
+ FileUtils.chdir(release_path) do
19
+ unless File.exist?("jobs") && File.exist?("packages")
20
+ raise Thor::Error.new("target path '#{release_path}' is not a BOSH release project")
21
+ end
22
+ end
23
+ end
24
+
25
+ # Create a deployment manifest (initially for AWS only)
26
+ def create_deployment_manifest
27
+ cloud_properties = { "instance_type" => "m1.small" }
28
+ manifest = Bosh::Gen::Models::DeploymentManifest.new(name, "DIRECTOR_UUID", cloud_properties)
29
+ manifest.jobs = job_manifests(ip_addresses)
30
+ create_file manifest_file_name, manifest.to_yaml, :force => flags[:force]
31
+ end
32
+
33
+ private
34
+ def jobs_dir(path = "")
35
+ File.join(release_path, "jobs", path)
36
+ end
37
+
38
+ # Whether +name+ contains .yml suffix or nor, returns a .yml filename for manifest to be generated
39
+ def manifest_file_name
40
+ basename = name.gsub(/\.yml/, '') + ".yml"
41
+ end
42
+
43
+ def job_manifests(ip_addresses)
44
+ jobs = detect_jobs.map do |job_name|
45
+ {
46
+ "name" => job_name
47
+ }
48
+ end
49
+ jobs.first["static_ips"] = ip_addresses if ip_addresses && ip_addresses.size > 0
50
+ jobs
51
+ end
52
+
53
+ # Return list of job names in this release based on the contents of jobs/* folder
54
+ def detect_jobs
55
+ Dir[File.join(release_path, "jobs/*")].map {|job_path| File.basename(job_path) }
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -6,7 +6,7 @@ module Bosh::Gen
6
6
  class JobGenerator < Thor::Group
7
7
  include Thor::Actions
8
8
 
9
- argument :name
9
+ argument :job_name
10
10
  argument :dependencies, :type => :array
11
11
 
12
12
  def self.source_root
@@ -20,7 +20,7 @@ module Bosh::Gen
20
20
  end
21
21
 
22
22
  def check_name
23
- raise Thor::Error.new("'#{name}' is not a vaild BOSH id") unless name.bosh_valid_id?
23
+ raise Thor::Error.new("'#{job_name}' is not a vaild BOSH id") unless job_name.bosh_valid_id?
24
24
  end
25
25
 
26
26
  def warn_missing_dependencies
@@ -32,26 +32,31 @@ module Bosh::Gen
32
32
  end
33
33
  end
34
34
 
35
- def templates
36
- empty_directory job_dir("templates")
35
+ def template_files
36
+ directory "jobs/%job_name%"
37
+ @template_files = { "#{job_name}_ctl" => "bin/#{job_name}_ctl" }
37
38
  end
38
39
 
39
- def monit
40
- create_file job_dir("monit"), ""
40
+ def ctl_executable
41
+ chmod "jobs/#{job_name}/templates/#{job_name}_ctl", 0755
41
42
  end
42
43
 
43
44
  def job_specification
44
- config = { "name" => name, "packages" => dependencies, "templates" => {} }
45
+ config = { "name" => job_name, "packages" => dependencies, "templates" => @template_files }
45
46
  create_file job_dir("spec"), YAML.dump(config)
46
47
  end
47
48
 
49
+ def show_todo
50
+ puts File.read(File.join(destination_root, "jobs", job_name, "TODO.md"))
51
+ end
52
+
48
53
  private
49
54
  def filenames
50
55
  files.map {|f| File.basename(f) }
51
56
  end
52
57
 
53
58
  def job_dir(path)
54
- File.join("jobs", name, path)
59
+ File.join("jobs", job_name, path)
55
60
  end
56
61
 
57
62
  # Run a command in git.
@@ -0,0 +1,4 @@
1
+ Next step for <%= job_name %> job:
2
+
3
+ * Replace "`exec /var/vcap/packages/redis/bin/EXECUTABLE_SERVER`" in jobs/<%= job_name %>/templates/<%= job_name %>_ctl
4
+
@@ -0,0 +1,5 @@
1
+ check process <%= job_name %>
2
+ with pidfile /var/vcap/sys/run/<%= job_name %>/<%= job_name %>.pid
3
+ start program "/var/vcap/jobs/<%= job_name %>/bin/<%= job_name %>_ctl start"
4
+ stop program "/var/vcap/jobs/<%= job_name %>/bin/<%= job_name %>_ctl stop"
5
+ group vcap
@@ -0,0 +1,35 @@
1
+ #!/bin/bash
2
+
3
+ # Control script to start/stop <%= job_name %> job on a BOSH controlled VM
4
+ #
5
+ # TODO - change "EXECUTABLE_SERVER" to the command to run
6
+ # TODO - ensure executable stores PID in $PIDFILE
7
+
8
+ RUN_DIR=/var/vcap/sys/run/<%= job_name %>
9
+ LOG_DIR=/var/vcap/sys/log/<%= job_name %>
10
+ STORE=/var/vcap/store/<%= job_name %>
11
+ PIDFILE=$RUN_DIR/<%= job_name %>.pid
12
+
13
+ case $1 in
14
+
15
+ start)
16
+ mkdir -p $RUN_DIR
17
+ mkdir -p $LOG_DIR
18
+ mkdir -p $STORE
19
+
20
+ echo $$ > $PIDFILE
21
+
22
+ exec /var/vcap/packages/<%= job_name %>/bin/EXECUTABLE_SERVER >>$LOG_DIR/<%= job_name %>.stdout.log 2>>$LOG_DIR/<%= job_name %>.stderr.log
23
+ ;;
24
+
25
+ stop)
26
+ PID=$(head -1 $PIDFILE)
27
+ kill $PID
28
+ while [ -e /proc/$PID ]; do sleep 0.1; done
29
+ rm -f $PIDFILE
30
+ ;;
31
+
32
+ *)
33
+ echo "Usage: <%= job_name %>_ctl {start|stop}" ;;
34
+ esac
35
+ exit 0
@@ -0,0 +1,7 @@
1
+ module Bosh
2
+ module Gen
3
+ module Models
4
+ end
5
+ end
6
+ end
7
+ require "bosh/gen/models/deployment_manifest"
@@ -0,0 +1,84 @@
1
+ require "yaml"
2
+
3
+ module Bosh::Gen::Models
4
+ class DeploymentManifest
5
+ attr_reader :manifest
6
+
7
+ def initialize(name, director_uuid, cloud_properties)
8
+ @manifest = {}
9
+ @cloud_properties = cloud_properties
10
+ @security_groups = ["default"]
11
+ @stemcell_version = "0.5.1"
12
+ @stemcell = { "name" => "bosh-stemcell", "version" => @stemcell_version }
13
+ manifest["name"] = name
14
+ manifest["director_uuid"] = director_uuid
15
+ manifest["release"] = { "name" => name, "version" => 1}
16
+ manifest["compilation"] = {
17
+ "workers" => 10,
18
+ "network" => "default",
19
+ "cloud_properties" => cloud_properties.dup
20
+ }
21
+ manifest["update"] = {
22
+ "canaries" => 1,
23
+ "canary_watch_time" => 30000,
24
+ "update_watch_time" => 30000,
25
+ "max_in_flight" => 4,
26
+ "max_errors" => 1
27
+ }
28
+ manifest["networks"] = [
29
+ {
30
+ "name" => "default",
31
+ "type" => "dynamic",
32
+ "cloud_properties" => { "security_groups" => @security_groups.dup }
33
+ },
34
+ {
35
+ "name" => "vip_network",
36
+ "type" => "vip",
37
+ "cloud_properties" => { "security_groups" => @security_groups.dup }
38
+ }
39
+ ]
40
+ manifest["resource_pools"] = [
41
+ {
42
+ "name" => "common",
43
+ "network" => "default",
44
+ "size" => 0,
45
+ "stemcell" => @stemcell,
46
+ "cloud_properties" => cloud_properties.dup
47
+ }
48
+ ]
49
+ manifest["jobs"] = []
50
+ manifest["properties"] = {}
51
+ end
52
+
53
+ def jobs=(jobs)
54
+ total_instances = 0
55
+ manifest["jobs"] = []
56
+ jobs.each do |job|
57
+ manifest_job = {
58
+ "name" => job["name"],
59
+ "template" => job["template"] || job["name"],
60
+ "instances" => job["instances"] || 1,
61
+ "resource_pool" => "common",
62
+ "networks" => [
63
+ {
64
+ "name" => "default",
65
+ "default" => %w[dns gateway]
66
+ }
67
+ ]
68
+ }
69
+ if job["static_ips"]
70
+ manifest_job["networks"] << {
71
+ "name" => "vip_network",
72
+ "static_ips" => job["static_ips"]
73
+ }
74
+ end
75
+ manifest["jobs"] << manifest_job
76
+ end
77
+ manifest["resource_pools"].first["size"] = manifest["jobs"].inject(0) {|total, job| total + job["instances"]}
78
+ end
79
+
80
+ def to_yaml
81
+ manifest.to_yaml
82
+ end
83
+ end
84
+ end
@@ -1,5 +1,5 @@
1
1
  module Bosh
2
2
  module Gen
3
- VERSION = "0.3.0"
3
+ VERSION = "0.3.2"
4
4
  end
5
5
  end
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: myproj
3
+ director_uuid: UUID
4
+ release:
5
+ name: myproj
6
+ version: 1
7
+ compilation:
8
+ workers: 10
9
+ network: default
10
+ cloud_properties:
11
+ instance_type: m1.small
12
+ update:
13
+ canaries: 1
14
+ canary_watch_time: 30000
15
+ update_watch_time: 30000
16
+ max_in_flight: 4
17
+ max_errors: 1
18
+ networks:
19
+ - name: default
20
+ type: dynamic
21
+ cloud_properties:
22
+ security_groups:
23
+ - default
24
+ - name: vip_network
25
+ type: vip
26
+ cloud_properties:
27
+ security_groups:
28
+ - default
29
+ resource_pools:
30
+ - name: common
31
+ network: default
32
+ size: 2
33
+ stemcell:
34
+ name: bosh-stemcell
35
+ version: 0.5.1
36
+ cloud_properties:
37
+ instance_type: m1.small
38
+ jobs:
39
+ - name: job-with-ips
40
+ template: job-with-ips
41
+ instances: 1
42
+ resource_pool: common
43
+ networks:
44
+ - name: default
45
+ default:
46
+ - dns
47
+ - gateway
48
+ - name: vip_network
49
+ static_ips:
50
+ - 1.2.3.4
51
+ - name: misc
52
+ template: misc
53
+ instances: 1
54
+ resource_pool: common
55
+ networks:
56
+ - name: default
57
+ default:
58
+ - dns
59
+ - gateway
60
+ properties: {}
@@ -0,0 +1,18 @@
1
+ require "minitest/spec"
2
+ require "minitest-colorize"
3
+ require "bosh/gen/models"
4
+
5
+ class DeploymentManifestSpec < MiniTest::Spec
6
+ it "creates 'defaults' manifest document with 2 jobs" do
7
+ manifest = Bosh::Gen::Models::DeploymentManifest.new("myproj", "UUID", {"instance_type" => "m1.small"})
8
+ manifest.jobs = [
9
+ { "name" => "job-with-ips", "static_ips" => ['1.2.3.4']},
10
+ { "name" => "misc"}
11
+ ]
12
+ manifest.to_yaml.must_equal fixture_manifest("defaults")
13
+ end
14
+
15
+ def fixture_manifest(name)
16
+ File.read(File.expand_path("../../fixtures/deployment_manifests/#{name}.yml", __FILE__))
17
+ end
18
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bosh-gen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-04 00:00:00.000000000 Z
12
+ date: 2012-05-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -59,6 +59,54 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: minitest
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '2.12'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '2.12'
78
+ - !ruby/object:Gem::Dependency
79
+ name: minitest-colorize
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: guard-minitest
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
62
110
  description: Generators for creating BOSH releases
63
111
  email:
64
112
  - drnicwilliams@gmail.com
@@ -70,6 +118,7 @@ files:
70
118
  - .gitignore
71
119
  - ChangeLog.md
72
120
  - Gemfile
121
+ - Guardfile
73
122
  - LICENSE
74
123
  - README.md
75
124
  - Rakefile
@@ -77,8 +126,12 @@ files:
77
126
  - bosh-gen.gemspec
78
127
  - lib/bosh/gen.rb
79
128
  - lib/bosh/gen/cli.rb
129
+ - lib/bosh/gen/generators/deployment_manifest_generator.rb
80
130
  - lib/bosh/gen/generators/job_generator.rb
81
131
  - lib/bosh/gen/generators/job_generator/templates/.gitkeep
132
+ - lib/bosh/gen/generators/job_generator/templates/jobs/%job_name%/TODO.md.tt
133
+ - lib/bosh/gen/generators/job_generator/templates/jobs/%job_name%/monit.tt
134
+ - lib/bosh/gen/generators/job_generator/templates/jobs/%job_name%/templates/%job_name%_ctl.tt
82
135
  - lib/bosh/gen/generators/job_template_generator.rb
83
136
  - lib/bosh/gen/generators/new_release_generator.rb
84
137
  - lib/bosh/gen/generators/new_release_generator/templates/README.md.tt
@@ -89,7 +142,11 @@ files:
89
142
  - lib/bosh/gen/generators/package_generator.rb
90
143
  - lib/bosh/gen/generators/package_generator/templates/.gitkeep
91
144
  - lib/bosh/gen/generators/package_source_generator.rb
145
+ - lib/bosh/gen/models.rb
146
+ - lib/bosh/gen/models/deployment_manifest.rb
92
147
  - lib/bosh/gen/version.rb
148
+ - spec/fixtures/deployment_manifests/defaults.yml
149
+ - spec/models/deployment_manifest_spec.rb
93
150
  homepage: https://github.com/drnic/bosh-gen
94
151
  licenses: []
95
152
  post_install_message:
@@ -104,7 +161,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
104
161
  version: '0'
105
162
  segments:
106
163
  - 0
107
- hash: -3342967338916077757
164
+ hash: -1671350536901681396
108
165
  required_rubygems_version: !ruby/object:Gem::Requirement
109
166
  none: false
110
167
  requirements:
@@ -113,11 +170,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
170
  version: '0'
114
171
  segments:
115
172
  - 0
116
- hash: -3342967338916077757
173
+ hash: -1671350536901681396
117
174
  requirements: []
118
175
  rubyforge_project:
119
176
  rubygems_version: 1.8.23
120
177
  signing_key:
121
178
  specification_version: 3
122
179
  summary: ''
123
- test_files: []
180
+ test_files:
181
+ - spec/fixtures/deployment_manifests/defaults.yml
182
+ - spec/models/deployment_manifest_spec.rb