bosh-gen 0.3.0 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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