knife-zcloudjp 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .chef/
19
+ *.swp
20
+ vendor/
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require fuubar
3
+ --format Fuubar
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - ree
6
+ # - jruby-19mode
7
+ - rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in knife-zcloudjp.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 HiganWorks LLC
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,158 @@
1
+ # Knife::Zcloudjp
2
+
3
+ [![Build Status](https://secure.travis-ci.org/higanworks/knife-zcloudjp.png)](http://travis-ci.org/higanworks/knife-zcloudjp)
4
+
5
+ A Knife(Opscode Chef) plugin for [Z Cloud](http://z-cloud.jp). This plugin allows you to retrieve product catalog, print the current machines and bootstrap a machine.
6
+
7
+ ## Installation
8
+
9
+ Drop the following line into your application's `Gemfile`.
10
+
11
+ gem 'knife-zcloudjp', :git => "git://github.com/higanworks/knife-zcloudjp.git"
12
+
13
+ And execute the `bundle` command.
14
+
15
+ $ bundle
16
+
17
+ ## Usage
18
+
19
+ Add the following entries to your `.chef/knife.rb`.
20
+
21
+ knife[:zcloudjp_api_token] = "YOUR-API-TOKEN"
22
+ knife[:zcloudjp_api_url] = "https://my.z-cloud.jp"
23
+
24
+ ### Retrieve the product catalog that are currently available.
25
+
26
+ $ knife zcloudjp product list (options)
27
+ name os dataset package
28
+ SmartOS Small 1 SmartOS sdc:sdc:smartos64:1.5.3 Small_1GB
29
+ SmartOS Medium 2 SmartOS sdc:sdc:smartos64:1.5.3 Medium_2GB
30
+ SmartOS Medium 4 SmartOS sdc:sdc:smartos64:1.5.3 Medium_4GB
31
+ SmartOS Large 8 SmartOS sdc:sdc:smartos64:1.5.3 Large_8GB
32
+ SmartOS Plus Small 1 SmartOS sdc:sdc:smartosplus64:3.0.7 Small_1GB
33
+ SmartOS Plus Medium 2 SmartOS sdc:sdc:smartosplus64:3.0.7 Medium_2GB
34
+ SmartOS Plus Medium 4 SmartOS sdc:sdc:smartosplus64:3.0.7 Medium_4GB
35
+ SmartOS Plus Large 8 SmartOS sdc:sdc:smartosplus64:3.0.7 Large_8GB
36
+ MySQL Small 1 SmartOS sdc:sdc:mysql:1.4.1 Small_1GB
37
+ MySQL Medium 2 SmartOS sdc:sdc:mysql:1.4.1 Medium_2GB
38
+ MySQL Medium 4 SmartOS sdc:sdc:mysql:1.4.1 Medium_4GB
39
+ MySQL Large 1 SmartOS sdc:sdc:mysql:1.4.1 Large_8GB
40
+
41
+
42
+ <pre><code>knife zcloudjp product list (options)
43
+ -s, --server-url URL Chef Server URL
44
+ -k, --key KEY API Client Key
45
+ --[no-]color Use colored output, defaults to enabled
46
+ -c, --config CONFIG The configuration file to use
47
+ --defaults Accept default values for all questions
48
+ -d, --disable-editing Do not open EDITOR, just accept the data as is
49
+ -e, --editor EDITOR Set the editor to use for interactive commands
50
+ -E, --environment ENVIRONMENT Set the Chef environment
51
+ -F, --format FORMAT Which format to use for output
52
+ -u, --user USER API Client Username
53
+ --print-after Show the data after a destructive operation
54
+ -V, --verbose More verbose output. Use twice for max verbosity
55
+ -v, --version Show chef version
56
+ -y, --yes Say yes to all prompts for confirmation
57
+ -K, --zcloudjp-api-token KEY Your Z cloud API token
58
+ --zcloudjp-api-auth-url URL Your Z Cloud API url
59
+ -h, --help Show this message
60
+ </code></pre>
61
+
62
+
63
+ ### Print the machine list
64
+
65
+ $ knife zcloudjp machine list (options)
66
+ name id ips dataset package state
67
+ Son_of_Jenkins_02 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ["210.152.xxx.xxx"] sdc:sdc:ubuntu10.04:0.1.0 Medium_2GB running
68
+ chef-sv01 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ["210.152.xxx.xxx"] sdc:sdc:ubuntu10.04:0.1.0 Small_1GB running
69
+ shinobra xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ["210.152.xxx.xxx"] sdc:sdc:smartos64:1.5.1 Small_1GB running
70
+ growthforecast xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ["210.152.xxx.xxx"] sdc:sdc:smartos64:1.5.3 Small_1GB running
71
+ rabi01 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ["210.152.xxx.xxx"] sdc:sdc:smartos64:1.5.3 Small_1GB running
72
+ zootest_south xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ["210.152.xxx.xxx"] sdc:sdc:smartos64:1.5.3 Small_1GB running
73
+
74
+ <pre><code>knife zcloudjp machine list (options)
75
+ -s, --server-url URL Chef Server URL
76
+ -k, --key KEY API Client Key
77
+ --[no-]color Use colored output, defaults to enabled
78
+ -c, --config CONFIG The configuration file to use
79
+ --defaults Accept default values for all questions
80
+ -d, --disable-editing Do not open EDITOR, just accept the data as is
81
+ -e, --editor EDITOR Set the editor to use for interactive commands
82
+ -E, --environment ENVIRONMENT Set the Chef environment
83
+ -F, --format FORMAT Which format to use for output
84
+ -u, --user USER API Client Username
85
+ --print-after Show the data after a destructive operation
86
+ -V, --verbose More verbose output. Use twice for max verbosity
87
+ -v, --version Show chef version
88
+ -y, --yes Say yes to all prompts for confirmation
89
+ -K, --zcloudjp-api-token KEY Your Z cloud API token
90
+ --zcloudjp-api-auth-url URL Your Z Cloud API url
91
+ -h, --help Show this message
92
+ </code></pre>
93
+
94
+ ### Create a new machine and integrate it to the Chef Server
95
+
96
+ $ knife zcloudjp machine create -I DATASET [-p PACKAGE] [-r role|recipie] (options)
97
+
98
+ Notice that the Linux virtual machine can be bootstrapped with the above command but the SmartMachine based on SmartOS can not be. To work out this issue, please refer to the following workaround.
99
+
100
+ #### Workaround for bootstrapping a machine based on SmartOS
101
+
102
+ Login into a newly provisonned machine based on SmartOS via ssh, and introduce the `chef-client` with the following commands.
103
+
104
+ # pkg_trans /tmp/chef-{version}.{arc}.solaris
105
+ # cp -rp chef/root/opt/chef /opt/
106
+ # /opt/chef/bin/chef-client
107
+
108
+ `client.rb` and `validation.pem` may be already stored in the `/etc/chef` directory. Now `chef-client` command is available on your machine, so you can perfome `run_list` with it.
109
+
110
+ <pre><code>knife zcloudjp machine create (options)
111
+ --bootstrap-version VERSION The version of Chef to install
112
+ -N, --node-name NAME The Chef node name for your new node (default uuid)
113
+ -s, --server-url URL Chef Server URL
114
+ -k, --key KEY API Client Key
115
+ --[no-]color Use colored output, defaults to enabled
116
+ -c, --config CONFIG The configuration file to use
117
+ -I DATASET_IMAGE, Dataset image of the machine
118
+ --dataset-image
119
+ --defaults Accept default values for all questions
120
+ --disable-editing Do not open EDITOR, just accept the data as is
121
+ -d, --distro DISTRO Bootstrap a distro using a template; default is 'chef-full'
122
+ -e, --editor EDITOR Set the editor to use for interactive commands
123
+ -E, --environment ENVIRONMENT Set the Chef environment
124
+ -j JSON_ATTRIBS, A JSON string to be added to the first run of chef-client
125
+ --json-attributes
126
+ -F, --format FORMAT Which format to use for output
127
+ --[no-]host-key-verify Verify host key, disabled by default
128
+ -i IDENTITY_FILE, The SSH identity file used for authentication
129
+ --identity-file
130
+ -n, --machine-name NAME Name tag value for your new machne (dafault uuid's first period)
131
+ -u, --user USER API Client Username
132
+ -p, --package PACKAGE Package of machine; default is Small_1GB
133
+ --prerelease Install the pre-release chef gems
134
+ --print-after Show the data after a destructive operation
135
+ -r, --run-list RUN_LIST Comma separated list of roles/recipes to apply
136
+ -x, --ssh-user USERNAME The ssh username; default is 'root'
137
+ --template-file TEMPLATE Full path to location of template to use
138
+ -V, --verbose More verbose output. Use twice for max verbosity
139
+ -v, --version Show chef version
140
+ -y, --yes Say yes to all prompts for confirmation
141
+ -K, --zcloudjp-api-token KEY Your Z cloud API token
142
+ --zcloudjp-api-auth-url URL Your Z Cloud API url
143
+ -M, --zcloud-metadata JSON JSON string version of metadata hash to be supplied with the machine create call
144
+ -h, --help Show this message
145
+ </code></pre>
146
+
147
+
148
+ ## Contributing
149
+
150
+ 1. Fork it
151
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
152
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
153
+ 4. Push to the branch (`git push origin my-new-feature`)
154
+ 5. Create new Pull Request
155
+
156
+ ## TODO
157
+
158
+ - Write specs and recactor the code.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require 'rubygems'
5
+ require 'rspec/core/rake_task'
6
+ require 'yard'
7
+
8
+ desc "Run all specs in spec directory"
9
+ RSpec::Core::RakeTask.new(:spec) do |t|
10
+ t.pattern = 'spec/unit/**/*_spec.rb'
11
+ t.rspec_opts = %w[--color]
12
+ end
13
+
14
+ YARD::Rake::YardocTask.new do |t|
15
+ t.files = ['lib/**/*.rb']
16
+ end
17
+
18
+ task :default => [:spec]
data/data/smartos.erb ADDED
@@ -0,0 +1,192 @@
1
+ bash -c '
2
+ <%= "export http_proxy=\"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] -%>
3
+
4
+ exists() {
5
+ if command -v $1 &>/dev/null
6
+ then
7
+ return 0
8
+ else
9
+ return 1
10
+ fi
11
+ }
12
+
13
+
14
+ if ! exists /opt/local/bin/chef-client; then
15
+ ## picked out from install.sh
16
+ version="<%= chef_version %>"
17
+ platform="solaris2"
18
+ machine=$(/usr/bin/uname -p)
19
+ platform_version=$(/usr/bin/uname -r)
20
+ filetype="solaris"
21
+ filename="chef-${version}.${machine}.solaris"
22
+
23
+ echo "Downloading Chef $version for ${platform}..."
24
+ url="https://www.opscode.com/chef/download?v=${version}&p=${platform}&pv=${platform_version}&m=${machine}"
25
+ tmp_dir=$(mktemp -d -t tmp.XXXXXXXX || echo "/tmp")
26
+
27
+ if exists wget;
28
+ then
29
+ downloader="wget"
30
+ wget --no-check-certificate -O "$tmp_dir/$filename" $url 2>/tmp/stderr
31
+ elif exists curl;
32
+ then
33
+ downloader="curl"
34
+ curl -k -L $url > "$tmp_dir/$filename"
35
+ else
36
+ echo "Cannot find wget or curl - cannot install Chef!"
37
+ exit 5
38
+ fi
39
+
40
+ # Check to see if we got a 404 or an empty file
41
+
42
+ unable_to_retrieve_package() {
43
+ echo "Unable to retrieve a valid package!"
44
+ echo "URL: $url"
45
+ exit 1
46
+ }
47
+
48
+ if [ $downloader == "curl" ]
49
+ then
50
+ #do curl stuff
51
+ grep "The specified key does not exist." "$tmp_dir/$filename" 2>&1 >/dev/null
52
+ if [ $? -eq 0 ] || [ ! -s "$tmp_dir/$filename" ]
53
+ then
54
+ unable_to_retrieve_package
55
+ fi
56
+ elif [ $downloader == "wget" ]
57
+ then
58
+ #do wget stuff
59
+ grep "ERROR 404" /tmp/stderr 2>&1 >/dev/null
60
+ if [ $? -eq 0 ] || [ ! -s "$tmp_dir/$filename" ]
61
+ then
62
+ unable_to_retrieve_package
63
+ fi
64
+ fi
65
+
66
+ echo "Installing Chef $version"
67
+
68
+ # functions for pkgtrans
69
+ _set_own(){
70
+ chown $2:$3 $1
71
+ }
72
+
73
+ _set_mod(){
74
+ chmod $2 $1
75
+ }
76
+
77
+ _set_sym(){
78
+ if [ ! -r $2 ];then continue; fi
79
+ ln -f -s $2 $1
80
+ }
81
+
82
+ _set_link(){
83
+ if [ ! -r $2 ];then continue; fi
84
+ mkdir -p `dirname $1`
85
+ ln -f $2 $1
86
+ }
87
+
88
+ _installer(){
89
+ # ignore first line
90
+ if [ "$1" = ":" ];then continue; fi
91
+
92
+ case $2 in
93
+ d)
94
+ if [ ! -d $4 ];then continue; fi
95
+ _set_own $4 $6 $7
96
+ _set_mod $4 $5
97
+ ;;
98
+ f)
99
+ if [ ! -f $4 ];then continue; fi
100
+ _set_own $4 $6 $7
101
+ _set_mod $4 $5
102
+ ;;
103
+ i)
104
+ # do nothing
105
+ :
106
+ ;;
107
+ l)
108
+ arr=( `echo $4 | tr -s "=" " "` )
109
+ _set_link ${arr[0]} ${arr[1]}
110
+ ;;
111
+ s)
112
+ arr=( `echo $4 | tr -s "=" " "` )
113
+ _set_sym ${arr[0]} `dirname ${arr[0]}`/${arr[1]}
114
+ ;;
115
+ esac
116
+ }
117
+
118
+ echo "Extracting to /opt/chef ..."
119
+ pkgtrans $tmp_dir/$filename $tmp_dir chef
120
+ cp -r $tmp_dir/chef/root/opt/chef /opt/
121
+
122
+ # main
123
+ echo "Fix permisssions and create links..."
124
+ while read LINE
125
+ do
126
+ _installer $LINE
127
+ done < $tmp_dir/chef/pkgmap
128
+
129
+ echo "Execute postinstall script."
130
+ sed -e "s@/usr/bin@/opt/local/bin@g" $tmp_dir/chef/install/postinstall | bash
131
+
132
+ if [ "$tmp_dir" != "/tmp" ];
133
+ then
134
+ rm -r "$tmp_dir"
135
+ fi
136
+
137
+ if [ $? -ne 0 ];
138
+ then
139
+ echo "Installation failed"
140
+ exit 1
141
+ fi
142
+
143
+ fi
144
+
145
+ mkdir -p /etc/chef
146
+
147
+ (
148
+ cat <<'EOP'
149
+ <%= validation_key %>
150
+ EOP
151
+ ) > /tmp/validation.pem
152
+ nawk NF /tmp/validation.pem > /etc/chef/validation.pem
153
+ rm /tmp/validation.pem
154
+ chmod 0600 /etc/chef/validation.pem
155
+
156
+ <% if @chef_config[:encrypted_data_bag_secret] -%>
157
+ (
158
+ cat <<'EOP'
159
+ <%= encrypted_data_bag_secret %>
160
+ EOP
161
+ ) > /tmp/encrypted_data_bag_secret
162
+ nawk NF /tmp/encrypted_data_bag_secret > /etc/chef/encrypted_data_bag_secret
163
+ rm /tmp/encrypted_data_bag_secret
164
+ chmod 0600 /etc/chef/encrypted_data_bag_secret
165
+ <% end -%>
166
+
167
+ <%# Generate Ohai Hints -%>
168
+ <% unless @chef_config[:knife][:hints].nil? || @chef_config[:knife][:hints].empty? -%>
169
+ mkdir -p /etc/chef/ohai/hints
170
+
171
+ <% @chef_config[:knife][:hints].each do |name, hash| -%>
172
+ (
173
+ cat <<'EOP'
174
+ <%= hash.to_json %>
175
+ EOP
176
+ ) > /etc/chef/ohai/hints/<%= name %>.json
177
+ <% end -%>
178
+ <% end -%>
179
+
180
+ (
181
+ cat <<'EOP'
182
+ <%= config_content %>
183
+ EOP
184
+ ) > /etc/chef/client.rb
185
+
186
+ (
187
+ cat <<'EOP'
188
+ <%= first_boot.to_json %>
189
+ EOP
190
+ ) > /etc/chef/first-boot.json
191
+
192
+ <%= start_chef %>'
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/knife-zcloudjp', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.version = Knife::Zcloudjp::VERSION
6
+ s.authors = ["sawanoboly"]
7
+ s.email = ["sawanoboriyu@gmail.com"]
8
+ s.description = %q{Knife(Opscode Chef) plugin for Z Cloud.}
9
+ s.summary = %q{Knife(Opscode Chef) plugin for Z Cloud.}
10
+ s.homepage = ""
11
+
12
+ s.files = `git ls-files`.split($\)
13
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
15
+ s.name = "knife-zcloudjp"
16
+ s.require_paths = ["lib"]
17
+
18
+ s.add_dependency "chef", ">= 0.10.10"
19
+ s.add_dependency "faraday"
20
+
21
+ s.add_development_dependency("rspec", [">= 2.2.0"])
22
+ s.add_development_dependency("yard", [">= 0.5.8"])
23
+ s.add_development_dependency("fuubar", [">= 0.0.1"])
24
+ s.add_development_dependency("rake")
25
+ end
@@ -0,0 +1,52 @@
1
+ require 'chef/knife'
2
+
3
+ class Chef
4
+ class Knife
5
+ module ZcloudjpBase
6
+
7
+ def self.included(includer)
8
+ includer.class_eval do
9
+
10
+ deps do
11
+ require 'net/ssh/multi'
12
+ require 'readline'
13
+ require 'chef/json_compat'
14
+ require 'faraday'
15
+ end
16
+
17
+ option :zcloudjp_api_token,
18
+ :short => "-K KEY",
19
+ :long => "--zcloudjp-api-token",
20
+ :description => "Your Z cloud API token",
21
+ :proc => Proc.new { |key| Chef::Config[:knife][:zcloudjp_api_token] = key }
22
+
23
+ option :zcloudjp_api_url,
24
+ :long => "--zcloudjp-api-auth-url URL",
25
+ :description => "Your Z Cloud API url",
26
+ :default => "https://my.z-cloud.jp",
27
+ :proc => Proc.new { |url| Chef::Config[:knife][:zcloudjp_api_url] = url }
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def connection
34
+ @connection = Faraday.new(:url => Chef::Config[:knife][:zcloudjp_api_url]) do |faraday|
35
+ faraday.request :url_encoded
36
+ end
37
+ end
38
+
39
+ def locate_config_value(key)
40
+ key = key.to_sym
41
+ Chef::Config[:knife][key] || config[key]
42
+ end
43
+
44
+ def msg_pair(label, value, color=:cyan)
45
+ if value && !value.to_s.empty?
46
+ puts "#{ui.color(label, color)}: #{value}"
47
+ end
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,230 @@
1
+ require 'chef/knife/zcloudjp_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class ZcloudjpMachineCreate < Knife
6
+ include ZcloudjpBase
7
+ banner "knife zcloudjp machine create (options)"
8
+
9
+
10
+ deps do
11
+ require 'net/ssh/multi'
12
+ require 'readline'
13
+ require 'chef/json_compat'
14
+ require 'faraday'
15
+ require 'chef/knife/bootstrap'
16
+ Chef::Knife::Bootstrap.load_deps
17
+ end
18
+
19
+ option :package,
20
+ :short => "-p PACKAGE",
21
+ :long => "--package PACKAGE",
22
+ :description => "Package of machine; default is Small_1GB",
23
+ :proc => Proc.new { |p| Chef::Config[:knife][:zcloudjp_package] = p },
24
+ :default => "Small_1GB"
25
+
26
+ option :dataset,
27
+ :short => "-I DATASET_IMAGE",
28
+ :long => "--dataset-image DATASET_IMAGE",
29
+ :description => "Dataset image of the machine",
30
+ :proc => Proc.new { |i| Chef::Config[:knife][:zcloudjp_dataset] = i }
31
+
32
+ option :machine_name,
33
+ :short => "-n NAME",
34
+ :long => "--machine-name NAME",
35
+ :description => "Name tag value for your new machne (dafault uuid's first period)"
36
+
37
+ option :chef_node_name,
38
+ :short => "-N NAME",
39
+ :long => "--node-name NAME",
40
+ :description => "The Chef node name for your new node (default uuid)"
41
+
42
+ option :ssh_user,
43
+ :short => "-x USERNAME",
44
+ :long => "--ssh-user USERNAME",
45
+ :description => "The ssh username; default is 'root'",
46
+ :default => "root"
47
+
48
+ option :identity_file,
49
+ :short => "-i IDENTITY_FILE",
50
+ :long => "--identity-file IDENTITY_FILE",
51
+ :description => "The SSH identity file used for authentication"
52
+
53
+ option :prerelease,
54
+ :long => "--prerelease",
55
+ :description => "Install the pre-release chef gems"
56
+
57
+ option :bootstrap_version,
58
+ :long => "--bootstrap-version VERSION",
59
+ :description => "The version of Chef to install",
60
+ :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
61
+
62
+ option :distro,
63
+ :short => "-d DISTRO",
64
+ :long => "--distro DISTRO",
65
+ :description => "Bootstrap a distro using a template; default is 'chef-full'",
66
+ :proc => Proc.new { |d| Chef::Config[:knife][:distro] = d },
67
+ :default => "chef-full"
68
+
69
+ option :template_file,
70
+ :long => "--template-file TEMPLATE",
71
+ :description => "Full path to location of template to use",
72
+ :proc => Proc.new { |t| Chef::Config[:knife][:template_file] = t },
73
+ :default => false
74
+
75
+ option :run_list,
76
+ :short => "-r RUN_LIST",
77
+ :long => "--run-list RUN_LIST",
78
+ :description => "Comma separated list of roles/recipes to apply",
79
+ :proc => lambda { |o| o.split(/[\s,]+/) },
80
+ :default => []
81
+
82
+ option :first_boot_attributes,
83
+ :short => "-j JSON_ATTRIBS",
84
+ :long => "--json-attributes",
85
+ :description => "A JSON string to be added to the first run of chef-client",
86
+ :proc => lambda { |o| JSON.parse(o) },
87
+ :default => {}
88
+
89
+ option :zcloudjp_metadata,
90
+ :short => "-M JSON",
91
+ :long => "--zcloud-metadata JSON",
92
+ :description => "JSON string version of metadata hash to be supplied with the machine create call",
93
+ :proc => Proc.new { |m| Chef::Config[:knife][:zcloudjp_metadata] = JSON.parse(m) },
94
+ :default => ""
95
+
96
+ option :host_key_verify,
97
+ :long => "--[no-]host-key-verify",
98
+ :description => "Verify host key, disabled by default",
99
+ :boolean => true,
100
+ :default => false
101
+
102
+
103
+ def verify_ssh_connection(hostname)
104
+ tcp_socket = TCPSocket.new(hostname, 22)
105
+ readable = IO.select([tcp_socket], nil, nil, 5)
106
+ if readable
107
+ Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
108
+ yield
109
+ true
110
+ else
111
+ false
112
+ end
113
+ rescue Errno::ETIMEDOUT
114
+ false
115
+ rescue Errno::EPERM
116
+ false
117
+ rescue Errno::ECONNREFUSED
118
+ sleep 2
119
+ false
120
+ rescue Errno::EHOSTUNREACH
121
+ sleep 2
122
+ false
123
+ rescue Errno::ENETUNREACH
124
+ sleep 2
125
+ false
126
+ ensure
127
+ tcp_socket && tcp_socket.close
128
+ end
129
+
130
+
131
+
132
+ def run
133
+ $stdout.sync = true
134
+
135
+ unless Chef::Config[:knife][:zcloudjp_dataset]
136
+ ui.error("You have not provided a valid dataset image value. Please note the short option for this value recently changed from '-i' to '-I'.")
137
+ exit 1
138
+ end
139
+ body = Hash.new()
140
+ body["dataset"] = config[:dataset]
141
+ body["package"] = locate_config_value(:package)
142
+ body["name"] = config[:chef_node_name]
143
+ body["locale"] = "en"
144
+
145
+ Chef::Log.debug("Create machine with parameters below")
146
+ Chef::Log.debug(body)
147
+
148
+
149
+ locate_config_value(:zcloudjp_api_url)
150
+ connection = Faraday.new(:url => locate_config_value(:zcloudjp_api_url), :ssl => {:verify => false})
151
+
152
+ response = connection.post do |req|
153
+ req.url '/machines.json'
154
+ req.headers['Content-Type'] = 'application/json'
155
+ req.headers['X-API-KEY'] = Chef::Config[:knife][:zcloudjp_api_token]
156
+ req.body = body.to_json
157
+ end
158
+
159
+ machine = JSON.parse(response.body, :symbolized_names =>true )
160
+
161
+ msg_pair("ID", machine['id'])
162
+ msg_pair("ip", machine['ips'].last)
163
+ msg_pair("type", machine['type'])
164
+ msg_pair("dataset", machine['dataset'])
165
+ msg_pair("package", machine['packeage'])
166
+ msg_pair("state", machine['state'])
167
+
168
+ bootstrap_ip_address = machine['ips'].last
169
+ config[:chef_node_name] = machine['id'] unless config[:chef_node_name]
170
+ config[:machine_name] = machine['id'].split("/")[0] unless config[:machine_name]
171
+
172
+ config[:first_boot_attributes]['zcloudjp'] = {}
173
+ config[:first_boot_attributes]['zcloudjp']['id'] = machine['id']
174
+ config[:first_boot_attributes]['zcloudjp']['type'] = machine['type']
175
+ config[:first_boot_attributes]['zcloudjp']['dataset'] = machine['dataset']
176
+
177
+
178
+
179
+ # wait for provision the machine.
180
+ print(".") until verify_ssh_connection(bootstrap_ip_address) {
181
+ sleep @initial_sleep_delay ||= 10
182
+ # puts("done")
183
+ }
184
+
185
+ # for smartdc workaround. check twice.
186
+ sleep 10
187
+
188
+ # wait for provision the machine.
189
+ print(".") until verify_ssh_connection(bootstrap_ip_address) {
190
+ sleep @initial_sleep_delay ||= 10
191
+ puts("done")
192
+ }
193
+
194
+ # add name tag for zcloud machine
195
+ body = Hash.new()
196
+ body["value"] = config[:machine_name]
197
+
198
+ response = connection.put do |req|
199
+ req.url "/machines/#{machine['id']}/name"
200
+ req.headers['Content-Type'] = 'application/json'
201
+ req.headers['X-API-KEY'] = Chef::Config[:knife][:zcloudjp_api_token]
202
+ req.body = body.to_json
203
+ end
204
+
205
+ bootstrap_node(machine, bootstrap_ip_address).run
206
+ end
207
+
208
+ def bootstrap_node(machine, bootstrap_ip_address)
209
+ bootstrap = Chef::Knife::Bootstrap.new
210
+ bootstrap.name_args = [bootstrap_ip_address]
211
+ bootstrap.config[:run_list] = config[:run_list]
212
+ bootstrap.config[:first_boot_attributes] = config[:first_boot_attributes]
213
+ bootstrap.config[:ssh_user] = config[:ssh_user] || "root"
214
+ # bootstrap.config[:ssh_password] = machine.password
215
+ bootstrap.config[:identity_file] = config[:identity_file]
216
+ bootstrap.config[:host_key_verify] = config[:host_key_verify]
217
+ bootstrap.config[:chef_node_name] = config[:chef_node_name] || server.id
218
+ bootstrap.config[:prerelease] = config[:prerelease]
219
+ bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
220
+ bootstrap.config[:distro] = locate_config_value(:distro)
221
+ # bootstrap will run as root...sudo (by default) also messes up Ohai on CentOS boxes
222
+ bootstrap.config[:use_sudo] = true unless config[:ssh_user] == 'root'
223
+ bootstrap.config[:template_file] = locate_config_value(:template_file)
224
+ bootstrap.config[:environment] = config[:environment]
225
+ bootstrap
226
+ end
227
+ end
228
+ end
229
+ end
230
+
@@ -0,0 +1,47 @@
1
+ require 'chef/knife/zcloudjp_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class ZcloudjpMachineList < Knife
6
+ include ZcloudjpBase
7
+
8
+ banner "knife zcloudjp machine list (options)"
9
+
10
+ def run
11
+ Chef::Log.debug("Connect to Z Cloud API #{locate_config_value(:zcloudjp_api_url)}")
12
+
13
+ connection = Faraday.new(:url => locate_config_value(:zcloudjp_api_url), :ssl => {:verify => false})
14
+
15
+ response = connection.get do |req|
16
+ req.url '/machines.json'
17
+ req.headers['Content-Type'] = 'application/json'
18
+ req.headers['X-API-KEY'] = Chef::Config[:knife][:zcloudjp_api_token]
19
+ end
20
+
21
+ machine_list = [
22
+ ui.color('name', :bold),
23
+ ui.color('id', :bold),
24
+ ui.color('ips', :bold),
25
+ ui.color('dataset', :bold),
26
+ ui.color('package', :bold),
27
+ ui.color('state', :bold),
28
+ ]
29
+
30
+ machines = JSON.parse(response.body)
31
+
32
+ machines.map do |machine|
33
+ machine_list << machine["name"].to_s
34
+ machine_list << machine["id"].to_s
35
+ machine_list << machine["ips"].to_s
36
+ machine_list << machine["dataset"]
37
+ machine_list << machine["package"]
38
+ machine_list << machine["state"]
39
+ end
40
+
41
+ puts ui.list(machine_list, :uneven_columns_across, 6)
42
+
43
+ end
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,40 @@
1
+ require 'chef/knife'
2
+
3
+ class Chef
4
+ class Knife
5
+ class ZcloudjpProductList < Knife
6
+ include ZcloudjpBase
7
+
8
+ banner "knife zcloudjp product list (options)"
9
+
10
+ def run
11
+ Chef::Log.debug("Connect to Z Cloud API #{locate_config_value(:zcloudjp_api_url)}")
12
+ connection = Faraday.new(:url => locate_config_value(:zcloudjp_api_url), :ssl => {:verify => false})
13
+
14
+ response = connection.get do |req|
15
+ req.url '/products.json'
16
+ req.headers['Content-Type'] = 'application/json'
17
+ req.headers['X-API-KEY'] = Chef::Config[:knife][:zcloudjp_api_token]
18
+ end
19
+
20
+ products = JSON.parse(response.body)
21
+
22
+ product_list = [
23
+ ui.color('name', :bold),
24
+ ui.color('os', :bold),
25
+ ui.color('dataset', :bold),
26
+ ui.color('package', :bold),
27
+ ]
28
+
29
+ products.map do |product|
30
+ product_list << product["name"]
31
+ product_list << product["os"]
32
+ product_list << product["sdc_dataset"]
33
+ product_list << product["sdc_package"]
34
+ end
35
+
36
+ puts ui.list(product_list, :uneven_columns_across, 4)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,6 @@
1
+ module Knife
2
+ module Zcloudjp
3
+ VERSION = "0.1.3"
4
+ MAJOR, MINOR, TINY = VERSION.split('.')
5
+ end
6
+ end
@@ -0,0 +1,12 @@
1
+ $:.unshift File.expand_path('../../lib', File.dirname(__FILE__))
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+
6
+ require 'rspec'
7
+ require 'chef'
8
+ require 'chef/knife/bootstrap'
9
+ require 'chef/knife/zcloudjp_base'
10
+ require 'chef/knife/zcloudjp_machine_create'
11
+ require 'chef/knife/zcloudjp_machine_list'
12
+ require 'chef/knife/zcloudjp_product_list'
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chef::Knife::ZcloudjpBase do
4
+ before do
5
+ end
6
+
7
+ describe "#self.included" do
8
+ it "should set up options to connect to the specified node"
9
+ end
10
+
11
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chef::Knife::ZcloudjpMachineCreate do
4
+ before do
5
+ end
6
+
7
+ describe "#verify_ssh_connection" do
8
+ it "should verify ssh connection with the specified node"
9
+ end
10
+
11
+ describe "#run" do
12
+ it "should create a machine with the specified options"
13
+ end
14
+
15
+ describe "#bootstrap_node" do
16
+ it "should bootstrap a specified node"
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chef::Knife::ZcloudjpMachineList do
4
+ before do
5
+ end
6
+
7
+ describe "#run" do
8
+ it "should retrieve all machines available for the current account"
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chef::Knife::ZcloudjpProductList do
4
+ before do
5
+ end
6
+
7
+ describe "#run" do
8
+ it "should retrive dynamically product data available for the current account"
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: knife-zcloudjp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - sawanoboly
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: chef
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.10.10
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.10.10
30
+ - !ruby/object:Gem::Dependency
31
+ name: faraday
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 2.2.0
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.2.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: yard
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 0.5.8
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: 0.5.8
78
+ - !ruby/object:Gem::Dependency
79
+ name: fuubar
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: 0.0.1
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.0.1
94
+ - !ruby/object:Gem::Dependency
95
+ name: rake
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'
110
+ description: Knife(Opscode Chef) plugin for Z Cloud.
111
+ email:
112
+ - sawanoboriyu@gmail.com
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - .gitignore
118
+ - .rspec
119
+ - .travis.yml
120
+ - Gemfile
121
+ - LICENSE
122
+ - README.md
123
+ - Rakefile
124
+ - data/smartos.erb
125
+ - knife-zcloudjp.gemspec
126
+ - lib/chef/knife/zcloudjp_base.rb
127
+ - lib/chef/knife/zcloudjp_machine_create.rb
128
+ - lib/chef/knife/zcloudjp_machine_list.rb
129
+ - lib/chef/knife/zcloudjp_product_list.rb
130
+ - lib/knife-zcloudjp.rb
131
+ - spec/spec_helper.rb
132
+ - spec/unit/zcloudjp_base_spec.rb
133
+ - spec/unit/zcloudjp_machine_create_spec.rb
134
+ - spec/unit/zcloudjp_machine_list_spec.rb
135
+ - spec/unit/zcloudjp_product_list_spec.rb
136
+ homepage: ''
137
+ licenses: []
138
+ post_install_message:
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ none: false
144
+ requirements:
145
+ - - ! '>='
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubyforge_project:
156
+ rubygems_version: 1.8.24
157
+ signing_key:
158
+ specification_version: 3
159
+ summary: Knife(Opscode Chef) plugin for Z Cloud.
160
+ test_files:
161
+ - spec/spec_helper.rb
162
+ - spec/unit/zcloudjp_base_spec.rb
163
+ - spec/unit/zcloudjp_machine_create_spec.rb
164
+ - spec/unit/zcloudjp_machine_list_spec.rb
165
+ - spec/unit/zcloudjp_product_list_spec.rb
166
+ has_rdoc: