kitchen-azure 0.1.0

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/.cane ADDED
File without changes
@@ -0,0 +1,17 @@
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
data/.tailor ADDED
@@ -0,0 +1,4 @@
1
+ Tailor.config do |config|
2
+ config.formatters "text"
3
+ config.file_set 'lib/**/*.rb'
4
+ end
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 2.0.0
5
+ - 1.9.3
6
+ - ruby-head
7
+
8
+ matrix:
9
+ allow_failures:
10
+ - rvm: ruby-head
@@ -0,0 +1,3 @@
1
+ ## 0.1.0 / Unreleased
2
+
3
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ Author:: Grant Ellis (<grant.ellis@mnscorp.net>)
2
+
3
+ Copyright (C) 2014, Grant Ellis
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
@@ -0,0 +1,103 @@
1
+ # <a name="title"></a> Kitchen::Msazure
2
+
3
+ A Test Kitchen Driver for Microsoft Azure.
4
+
5
+ ## <a name="requirements"></a> Requirements
6
+
7
+ * A Microsoft Azure account
8
+ * An Azure subscription
9
+ * A `.publishsettings` file with the subscription definition and
10
+ management certificate
11
+
12
+ ## <a name="installation"></a> Installation and Setup
13
+
14
+ The most basic configuration required is show below. Specify this in the
15
+ .kitchen.yml file
16
+
17
+ ```yaml
18
+ driver:
19
+ name: azure
20
+ subscription: "SubscriptionName"
21
+ publish_settings_file: "/path/to/publishsettings"
22
+ storage_account: "StorageAccountName"
23
+ ```
24
+
25
+ Platforms currently supported:
26
+
27
+ ```yaml
28
+ platforms:
29
+ - name: centos-6.3
30
+ - name: centos-6.4
31
+ - name: centos-6.5
32
+ - name: ubuntu-12.04
33
+ - name: ubuntu-13.10
34
+ - name: ubuntu-14.04
35
+ ```
36
+
37
+ Please read the [Driver usage][driver_usage] page for more details.
38
+
39
+ ## <a name="config"></a> Configuration
40
+
41
+ Below is a list of the configuration options, their obligatoriness and defaults
42
+
43
+ * ### <a name="config-pub-settings"></a> publish_settings_file
44
+ **Required** Path to publish settings file
45
+ Either specify as an environment variable `PUBLISH_SETTINGS_FILE=/path/to/file`
46
+ or in the .kitchen.yml file
47
+
48
+ * ### <a name="config-subscription"></a> subscription
49
+ **Required** Name of Azure subscription
50
+ Either specify as an environment variable `SUBSCRIPTION=SubscriptionName`
51
+ or in the .kitchen.yml file
52
+
53
+ * ### <a name="config-subscription"></a> storage_account
54
+ **Required** Name of the storage account to use
55
+ Either specify as an environment variable `STORAGE_ACCOUNT=StorageAccountName`
56
+ or in the .kitchen.yml file
57
+
58
+ * ### <a name="config-ssh"></a> port
59
+ The SSH port to use
60
+ **Default:** 2222
61
+
62
+ * ### <a name="config-username"></a> username
63
+ The VM username to use
64
+ **Default:** azureuser
65
+
66
+ * ### <a name="config-location"></a> location
67
+ The Azure datacenter location to use
68
+ **Default:** East US
69
+
70
+ * ### <a name="config-size"></a> size
71
+ The size of the VM to create
72
+ **Default:** small
73
+
74
+ ## <a name="development"></a> Development
75
+
76
+ * Source hosted at [GitHub][repo]
77
+ * Report issues/questions/feature requests on [GitHub Issues][issues]
78
+
79
+ Pull requests are very welcome! Make sure your patches are well tested.
80
+ Ideally create a topic branch for every separate change you make. For
81
+ example:
82
+
83
+ 1. Fork the repo
84
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
85
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
86
+ 4. Push to the branch (`git push origin my-new-feature`)
87
+ 5. Create new Pull Request
88
+
89
+ ## <a name="authors"></a> Authors
90
+
91
+ Created and maintained by [Grant Ellis][author] (<grant.ellis@marks-and-spencer.com>)
92
+
93
+ ## <a name="license"></a> License
94
+
95
+ Apache 2.0 (see [LICENSE][license])
96
+
97
+
98
+ [author]: https://github.com/DigitalInnovation
99
+ [issues]: https://github.com/DigitalInnovation/kitchen-azure/issues
100
+ [license]: https://github.com/DigitalInnovation/kitchen-azure/blob/master/LICENSE
101
+ [repo]: https://github.com/DigitalInnovation/kitchen-azure
102
+ [driver_usage]: http://docs.kitchen-ci.org/drivers/usage
103
+ [chef_omnibus_dl]: http://www.getchef.com/chef/install/
@@ -0,0 +1,25 @@
1
+ require "bundler/gem_tasks"
2
+ require 'cane/rake_task'
3
+ require 'tailor/rake_task'
4
+
5
+ desc "Run cane to check quality metrics"
6
+ Cane::RakeTask.new do |cane|
7
+ cane.canefile = './.cane'
8
+ end
9
+
10
+ Tailor::RakeTask.new
11
+
12
+ desc "Display LOC stats"
13
+ task :stats do
14
+ puts "\n## Production Code Stats"
15
+ sh "countloc -r lib"
16
+ end
17
+
18
+ task :build do
19
+ sh "gem build kitchen-azure.gemspec"
20
+ end
21
+
22
+ desc "Run all quality tasks"
23
+ task :quality => [:stats]
24
+
25
+ task :default => [:quality, :build]
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kitchen/driver/azure_version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'kitchen-azure'
8
+ spec.version = Kitchen::Driver::MSAZURE_VERSION
9
+ spec.authors = ['Grant Ellis']
10
+ spec.email = ['grant.ellis@marks-and-spencer.com']
11
+ spec.description = %q{A Test Kitchen Driver for Microsoft Azure}
12
+ spec.summary = 'Builds test-kitchen Linux VMs in Microsoft Azure'
13
+ spec.homepage = 'https://github.com/DigitalInnovation/kitchen-azure'
14
+ spec.license = 'Apache 2.0'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = []
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'test-kitchen', '~> 1.2'
22
+ spec.add_dependency 'nokogiri'
23
+ spec.add_dependency 'azure'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.3'
26
+ spec.add_development_dependency 'rake'
27
+ spec.add_development_dependency 'cane'
28
+ spec.add_development_dependency 'tailor'
29
+ spec.add_development_dependency 'countloc'
30
+ end
@@ -0,0 +1,184 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Grant Ellis (<grant.ellis@marks-and-spencer.com>)
4
+ #
5
+ # Copyright (C) 2014, Grant Ellis
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require 'azure'
20
+ require 'securerandom'
21
+ require 'openssl'
22
+ require 'nokogiri'
23
+ require 'kitchen'
24
+
25
+ module Kitchen
26
+
27
+ module Driver
28
+
29
+ # Azure driver for Kitchen.
30
+ #
31
+ # @author Grant Ellis <grant.ellis@marks-and-spencer.com>
32
+ class Azure < Kitchen::Driver::SSHBase
33
+
34
+ AZURE_MANAGEMENT_ENDPOINT='https://management.core.windows.net'
35
+ default_config :port, 2222
36
+ default_config :username, 'azureuser'
37
+ default_config :location, 'East US'
38
+ default_config :size, 'Small'
39
+ default_config :publish_settings_file do |driver|
40
+ ENV['PUBLISH_SETTINGS_FILE']
41
+ end
42
+ default_config :subscription do |driver|
43
+ ENV['SUBSCRIPTION']
44
+ end
45
+ default_config :storage_account do |driver|
46
+ ENV['STORAGE_ACCOUNT']
47
+ end
48
+
49
+ required_config :publish_settings_file
50
+ required_config :subscription
51
+ required_config :storage_account
52
+
53
+ def create(state)
54
+ if state[:cloud_service]
55
+ info("Already created: #{instance.name}")
56
+ return
57
+ end
58
+ azure_configure
59
+ debug("Config: #{config.inspect}")
60
+ debug("Platform: #{instance.platform.name}")
61
+ info("Searching for images for distro #{instance.platform.name}")
62
+ distro = instance.platform.name.match(/(\w+)[\-_](\d+)[\-_\.](\d+)/)
63
+ @cloud_service = "test-kitchen-" + SecureRandom.hex(6)
64
+ if (distro.nil? || (distro.length != 4))
65
+ raise 'Unable to parse linux distro'
66
+ end
67
+
68
+ flavour = distro[1]
69
+ maj = distro[2]
70
+ min = distro[3]
71
+ vmis = ::Azure::VirtualMachineImageManagementService.new
72
+ image = vmis.list_virtual_machine_images.select{ |i| i.name =~ /#{flavour}.*#{maj}[\-_\.]#{min}/i }.last
73
+ raise "Unable to find matching image for #{instance.platform.name}" if image.nil?
74
+
75
+ generate_ssh_certs
76
+
77
+ vm_params = {
78
+ :vm_name => instance.name,
79
+ :vm_user => config[:username],
80
+ :image => image.name,
81
+ :location => config[:location]
82
+ }
83
+ vm_options = {
84
+ :storage_account_name => config[:storage_account],
85
+ :ssh_port => config[:port],
86
+ :cloud_service_name => @cloud_service,
87
+ :vm_size => config[:size],
88
+ :private_key_file => File.join(cert_dir , 'azure.key'),
89
+ :certificate_file => File.join(cert_dir , 'azure.pem')
90
+ }
91
+
92
+ @instance_opts = vm_params.merge(vm_options)
93
+
94
+ state[:hostname] = "#{@cloud_service}.cloudapp.net"
95
+ state[:ssh_key] = vm_options[:private_key_file]
96
+ state[:vm_name] = vm_params[:vm_name]
97
+ state[:cloud_service] = vm_options[:cloud_service_name]
98
+
99
+ debug('Instance Options: ' + @instance_opts.inspect)
100
+
101
+ vms = ::Azure::VirtualMachineManagementService.new
102
+ vms.create_virtual_machine(vm_params, vm_options)
103
+
104
+ # Logic to wait until VM is ReadyRole
105
+ while ((vm_status = vms.list_virtual_machines.find{ |vm| vm.vm_name == instance.name }.status) != 'ReadyRole')
106
+ info("Waiting for VM to be ready. Current state: #{vm_status}")
107
+ sleep 10
108
+ end
109
+
110
+ wait_for_sshd(state[:hostname], config[:username], { :port => config[:port] })
111
+ end
112
+
113
+ def destroy(state)
114
+ return unless state[:hostname]
115
+ azure_configure
116
+ vms = ::Azure::VirtualMachineManagementService.new
117
+ vms.delete_virtual_machine(state[:vm_name], state[:cloud_service])
118
+ FileUtils.rm_r(azure_temp_dir)
119
+ end
120
+
121
+ private
122
+
123
+ def azure_configure
124
+
125
+ begin
126
+ settings = Nokogiri::XML(File.open(config[:publish_settings_file]))
127
+ sub_data = settings.xpath("//Subscription").find{ |s| s.attributes['Name'].value == config[:subscription]}
128
+ raise "Couldn't find subscription" unless sub_data
129
+ cert = sub_data['ManagementCertificate']
130
+ raise "Couldn't parse certificate" unless cert
131
+ sub_id = sub_data['Id']
132
+ raise "Couldn't get Subscription Id" unless sub_id
133
+ rescue Exception => e
134
+ raise "Error parsing publishsettings file: #{e.message}"
135
+ end
136
+
137
+ cert_file = File.join(config[:kitchen_root], %w{.kitchen kitchen-azure}, 'management_cert.pfx')
138
+
139
+ FileUtils.mkdir_p(File.join(config[:kitchen_root], %w{.kitchen kitchen-azure}))
140
+ File.open(cert_file,"w") do |f|
141
+ f.write(cert)
142
+ end
143
+
144
+ ::Azure.configure do |c|
145
+ c.management_certificate = cert_file
146
+ c.subscription_id = sub_id
147
+ c.management_endpoint = AZURE_MANAGEMENT_ENDPOINT
148
+ end
149
+ end
150
+
151
+ def azure_temp_dir
152
+ @az_tmp_dir ||= File.join(
153
+ config[:kitchen_root], %w{.kitchen kitchen-azure}, instance.name
154
+ )
155
+ end
156
+
157
+ def cert_dir
158
+ @cert_dir ||= File.join(azure_temp_dir, ".ssh")
159
+ end
160
+
161
+ def generate_ssh_certs
162
+ if File.exists?(File.join(cert_dir, "azure.key")) && File.exists?(File.join(cert_dir , "azure.pem"))
163
+ debug("certificate files already exist")
164
+ return
165
+ end
166
+
167
+ FileUtils.mkdir_p(cert_dir)
168
+ FileUtils.chmod(0700, cert_dir)
169
+ key = OpenSSL::PKey::RSA.new 2048
170
+ cert = OpenSSL::X509::Certificate.new
171
+ cert.version = 2
172
+ cert.serial = 0
173
+ cert.not_before = Time.now
174
+ cert.not_after = Time.now + 3600
175
+ cert.public_key = key.public_key
176
+
177
+ open(cert_dir + "/azure.key","w",0600) { |io| io.write(key.to_pem) }
178
+ open(cert_dir + "/azure.pem","w",0600) { |io| io.write(cert.to_pem) }
179
+ end
180
+
181
+ end
182
+
183
+ end
184
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Grant Ellis (<grant.ellis@marks-and-spencer.com>)
4
+ #
5
+ # Copyright (C) 2014, Grant Ellis
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ module Kitchen
20
+
21
+ module Driver
22
+
23
+ # Version string for Msazure Kitchen driver
24
+ MSAZURE_VERSION = "0.1.0"
25
+ end
26
+ end
metadata ADDED
@@ -0,0 +1,192 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kitchen-azure
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Grant Ellis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-06-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: test-kitchen
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.2'
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: '1.2'
30
+ - !ruby/object:Gem::Dependency
31
+ name: nokogiri
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: azure
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: bundler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.3'
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: '1.3'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
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: cane
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
+ - !ruby/object:Gem::Dependency
111
+ name: tailor
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: countloc
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ description: A Test Kitchen Driver for Microsoft Azure
143
+ email:
144
+ - grant.ellis@marks-and-spencer.com
145
+ executables: []
146
+ extensions: []
147
+ extra_rdoc_files: []
148
+ files:
149
+ - .cane
150
+ - .gitignore
151
+ - .tailor
152
+ - .travis.yml
153
+ - CHANGELOG.md
154
+ - Gemfile
155
+ - LICENSE
156
+ - README.md
157
+ - Rakefile
158
+ - kitchen-azure.gemspec
159
+ - lib/kitchen/driver/azure.rb
160
+ - lib/kitchen/driver/azure_version.rb
161
+ homepage: https://github.com/DigitalInnovation/kitchen-azure
162
+ licenses:
163
+ - Apache 2.0
164
+ post_install_message:
165
+ rdoc_options: []
166
+ require_paths:
167
+ - lib
168
+ required_ruby_version: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ segments:
175
+ - 0
176
+ hash: -1923809995946746477
177
+ required_rubygems_version: !ruby/object:Gem::Requirement
178
+ none: false
179
+ requirements:
180
+ - - ! '>='
181
+ - !ruby/object:Gem::Version
182
+ version: '0'
183
+ segments:
184
+ - 0
185
+ hash: -1923809995946746477
186
+ requirements: []
187
+ rubyforge_project:
188
+ rubygems_version: 1.8.23
189
+ signing_key:
190
+ specification_version: 3
191
+ summary: Builds test-kitchen Linux VMs in Microsoft Azure
192
+ test_files: []