chef-provisioning-upcloud 0.2.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6696f303371737ddc6cf49450260ac618ab132da
4
+ data.tar.gz: 2eea17ad6ff8a0010e8a25aeadcc9e77217f320c
5
+ SHA512:
6
+ metadata.gz: db6caf7c6052385178278c4fde338b544315fdc4409a3b3702253b83f1d68592459abd7d8b8baa9ed2b558b29f8081b1efbcabf4cfd2f8384b6eb0de6386d6be
7
+ data.tar.gz: f5f38fb1116cbafe5dff96b33ab8916cdaaf6d527e05761db0e3cd71519d01958f23bd95894704ff20c14014ae519f5f53b5514a3c38181dcd494495f3e1a89e
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ ## 0.2.0 (2016-01-11)
2
+
3
+ - Rewrite whole logic to Interactors.
4
+ - Fix formatting.
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # chef-provisioning-upcloud
2
+
3
+ **Pull requests are encouraged and greatly appreciated!**
4
+
5
+ ## Warning - there will be dragons
6
+
7
+ - Use at your own risk.
8
+ - It's POC, created just for fun and maybe to learn something.
9
+
10
+ ## What doesn't work
11
+
12
+ - `action :destroy` won't delete disks.
13
+
14
+ ## Quick start
15
+
16
+ ### knife.rb
17
+
18
+ ```ruby
19
+ current_dir = File.dirname(__FILE__)
20
+ cookbook_copyright "Szymon Szypulski"
21
+ cookbook_email "szymon.szypulski@gmail.com"
22
+ log_level :info
23
+ log_location STDOUT
24
+ node_name "szymon"
25
+ client_key "#{ENV["HOME"]}/.chef_priv/szymon.pem"
26
+ validation_client_name "organization-validator"
27
+ validation_key "#{ENV["HOME"]}/.chef_priv/organization-validator.pem"
28
+ chef_server_url "https://api.opscode.com/organizations/organization"
29
+ cookbook_path ["./cookbooks"]
30
+ profiles(
31
+ "default" => {},
32
+ "openday" => {
33
+ driver: "upcloud:openday",
34
+ machine_options: {
35
+ bootstrap_options: {
36
+ # https://api.upcloud.com/1.2/storage/template
37
+ template: "01000000-0000-4000-8000-000030040200", # Ubuntu 14.04
38
+ # https://api.upcloud.com/1.2/zone
39
+ zone: "uk-lon1",
40
+ # https://api.upcloud.com/1.2/plan
41
+ plan: "1xCPU-1GB"
42
+ }
43
+ }
44
+ }
45
+ )
46
+ drivers(
47
+ "upcloud:openday" => {
48
+ driver_options: {
49
+ compute_options: {
50
+ auth_token: "<base64 from upcloud user+":"+password>"
51
+ }
52
+ }
53
+ }
54
+ )
55
+ ```
56
+
57
+ ### provision.rb
58
+
59
+ ```ruby
60
+ require "chef/provisioning/upcloud_driver/driver"
61
+
62
+ with_chef_server Chef::Config[:chef_server_url],
63
+ client_name: Chef::Config[:node_name],
64
+ signing_key_filename: Chef::Config[:client_key]
65
+
66
+ machine "web1.tld.com"
67
+ ```
68
+
69
+ ### Execution
70
+
71
+ ```
72
+ CHEF_PROFILE=openday chef-client -c knife.rb provision.rb
73
+ ```
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ require 'bundler/gem_tasks'
@@ -0,0 +1,6 @@
1
+ require "chef/provisioning/upcloud_driver/driver"
2
+
3
+ Chef::Provisioning.register_driver_class(
4
+ "upcloud",
5
+ Chef::Provisioning::UpcloudDriver::Driver
6
+ )
@@ -0,0 +1 @@
1
+ class Base; end
@@ -0,0 +1,15 @@
1
+ class Base::DestroyMachine
2
+ include Interactor
3
+
4
+ # @param client
5
+ # @param action_handler
6
+ # @param machine_spec
7
+ def call
8
+ machine_id = context.machine_spec.reference["server_id"]
9
+ context.action_handler.perform_action "Destroy machine #{machine_id}\n" do
10
+ # delete all disks too
11
+ context.client.delete("server/#{machine_id}")
12
+ context.machine_spec.reference = nil
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ class Base::GetMachine
2
+ include Interactor
3
+
4
+ # @param client
5
+ # @param action_handler (optional)
6
+ # @param machine_spec
7
+ def call
8
+ machine_id = context.machine_spec.reference["server_id"]
9
+ response = context.client.get("server/#{machine_id}")
10
+ case response.status_code
11
+ when 404
12
+ context.action_handler.perform_action "Machine #{machine_id} does not exist.\n" do
13
+ context.machine_spec.reference = nil
14
+ end if context.action_handler
15
+ context.machine = nil
16
+ when 200
17
+ puts "Machine #{machine_id} exist.\n"
18
+ context.machine = JSON.parse(response.body)["server"]
19
+ else
20
+ fail "Unexpected response"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ class Base::InitializeClient
2
+ include Interactor
3
+
4
+ # @param auth_token
5
+ def call
6
+ client = Hurley::Client.new "https://api.upcloud.com/1.2/"
7
+ client.header["Authorization"] = "Basic #{context.auth_token}"
8
+ client.header["Content-Type"] = "application/json"
9
+
10
+ context.client = client
11
+ end
12
+ end
@@ -0,0 +1,24 @@
1
+ class Base::ReadyMachine
2
+ include Interactor
3
+
4
+ # @param client
5
+ # @param action_handler
6
+ # @param machine_spec
7
+ def call
8
+ client = context.client
9
+ machine_id = context.machine_spec.reference["server_id"]
10
+
11
+ machine = GetMachine.call(*context).machine
12
+ return if machine["state"] == "started"
13
+ context.action_handler.perform_action "Powering up, wait for machine #{machine_id}\n" do
14
+ client.post("server/#{machine_id}/start")
15
+ while machine["state"] != "started"
16
+ Timeout.timeout(60) do
17
+ sleep 5
18
+ client.post("server/#{machine_id}/start")
19
+ machine = GetMachine.call(*context).machine
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,52 @@
1
+ require "chef/provisioning/upcloud_driver/version"
2
+
3
+ class Base::RequestMachine
4
+ include Interactor
5
+
6
+ # @param client
7
+ # @param action_handler
8
+ # @param machine_spec
9
+ # @param driver_url
10
+ def call
11
+ machine_options = context.machine_options
12
+ machine_spec = context.machine_spec
13
+
14
+ context.action_handler.perform_action "Creating server #{machine_spec.name} with options #{machine_options}\n" do
15
+ response = context.client.post("server", request_body(machine_options, machine_spec).to_json, "application/json")
16
+ if response.success?
17
+ server = JSON.parse(response.body)["server"]
18
+
19
+ machine_spec.reference = {
20
+ "driver_url" => context.driver_url,
21
+ "driver_version" => ::Chef::Provisioning::UpcloudDriver::VERSION,
22
+ "server_id" => server["uuid"],
23
+ "bootstrap_password" => server["password"]
24
+ }
25
+ else
26
+ fail "Unexpected response: #{response.body}"
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def request_body(machine_options, machine_spec)
34
+ {
35
+ server: {
36
+ zone: machine_options[:bootstrap_options][:zone],
37
+ title: machine_spec.name,
38
+ hostname: machine_spec.name,
39
+ plan: machine_options[:bootstrap_options][:plan],
40
+ storage_devices: {
41
+ storage_device: [{
42
+ action: "clone",
43
+ storage: machine_options[:bootstrap_options][:template],
44
+ title: "#{machine_spec.name} from a template",
45
+ size: 30,
46
+ tier: "maxiops"
47
+ }]
48
+ }
49
+ }
50
+ }
51
+ end
52
+ end
@@ -0,0 +1,21 @@
1
+ class Base::StopMachine
2
+ include Interactor
3
+
4
+ # @param client
5
+ # @param action_handler
6
+ # @param machine_spec
7
+ def call
8
+ machine_id = context.machine_spec.reference["server_id"]
9
+ context.action_handler.perform_action "Power off machine #{machine_id}\n" do
10
+ context.client.post("server/#{machine_id}/stop")
11
+ end
12
+
13
+ machine = GetMachine.call(*context).machine
14
+ while machine["state"] != "stopped"
15
+ Timeout.timeout(60) do
16
+ sleep 20
17
+ machine = GetMachine.call(*context).machine
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,10 @@
1
+ require "chef/provisioning/interactors/base"
2
+ require "chef/provisioning/interactors/base/destroy_machine"
3
+ require "chef/provisioning/interactors/base/initialize_client"
4
+ require "chef/provisioning/interactors/base/stop_machine"
5
+
6
+ class DestroyMachine
7
+ include Interactor::Organizer
8
+
9
+ organize Base::InitializeClient, Base::StopMachine, Base::DestroyMachine
10
+ end
@@ -0,0 +1,9 @@
1
+ require "chef/provisioning/interactors/base"
2
+ require "chef/provisioning/interactors/base/get_machine"
3
+ require "chef/provisioning/interactors/base/initialize_client"
4
+
5
+ class GetMachine
6
+ include Interactor::Organizer
7
+
8
+ organize Base::InitializeClient, Base::GetMachine
9
+ end
@@ -0,0 +1,9 @@
1
+ require "chef/provisioning/interactors/base"
2
+ require "chef/provisioning/interactors/base/initialize_client"
3
+ require "chef/provisioning/interactors/base/ready_machine"
4
+
5
+ class ReadyMachine
6
+ include Interactor::Organizer
7
+
8
+ organize Base::InitializeClient, Base::ReadyMachine
9
+ end
@@ -0,0 +1,9 @@
1
+ require "chef/provisioning/interactors/base"
2
+ require "chef/provisioning/interactors/base/request_machine"
3
+ require "chef/provisioning/interactors/base/initialize_client"
4
+
5
+ class RequestMachine
6
+ include Interactor::Organizer
7
+
8
+ organize Base::InitializeClient, Base::RequestMachine
9
+ end
@@ -0,0 +1,9 @@
1
+ require "chef/provisioning/interactors/base"
2
+ require "chef/provisioning/interactors/base/stop_machine"
3
+ require "chef/provisioning/interactors/base/initialize_client"
4
+
5
+ class StopMachine
6
+ include Interactor::Organizer
7
+
8
+ organize Base::InitializeClient, Base::StopMachine
9
+ end
@@ -0,0 +1,3 @@
1
+ require "chef/provisioning"
2
+ require "chef/provisioning/upcloud_driver/driver"
3
+ require "chef/provisioning/upcloud_driver/resources"
@@ -0,0 +1,96 @@
1
+ require "chef/provisioning/driver"
2
+ require "chef/provisioning/upcloud_driver/version"
3
+
4
+ require "chef/provisioning/transport/ssh"
5
+ require "chef/provisioning/convergence_strategy/install_cached"
6
+ require "chef/provisioning/machine/unix_machine"
7
+
8
+ require "hurley"
9
+ require "interactor"
10
+
11
+ require "chef/provisioning/interactors/destroy_machine"
12
+ require "chef/provisioning/interactors/get_machine"
13
+ require "chef/provisioning/interactors/ready_machine"
14
+ require "chef/provisioning/interactors/request_machine"
15
+ require "chef/provisioning/interactors/stop_machine"
16
+
17
+ class Chef
18
+ module Provisioning
19
+ module UpcloudDriver
20
+ class Driver < Chef::Provisioning::Driver
21
+ include Chef::Mixin::ShellOut
22
+
23
+ def self.from_url(driver_url, config)
24
+ Driver.new(driver_url, config)
25
+ end
26
+
27
+ def initialize(driver_url, config)
28
+ super
29
+
30
+ begin
31
+ @auth_token = config[:driver_options][:compute_options][:auth_token]
32
+ rescue NoMethodError
33
+ msg = "Auth token is missing"
34
+ Chef::Log.fatal msg
35
+ raise msg
36
+ end
37
+ end
38
+
39
+ def self.canonicalize_url(driver_url, config)
40
+ [driver_url, config]
41
+ end
42
+
43
+ def allocate_machine(action_handler, machine_spec, machine_options)
44
+ if machine_spec.reference
45
+ GetMachine.call(action_handler: action_handler, auth_token: @auth_token, machine_spec: machine_spec)
46
+ end
47
+ return if machine_spec.reference
48
+ RequestMachine.call(
49
+ action_handler: action_handler, auth_token: @auth_token, driver_url: driver_url,
50
+ machine_options: machine_options, machine_spec: machine_spec
51
+ )
52
+ end
53
+
54
+ def stop_machine(action_handler, machine_spec, _machine_options)
55
+ return unless machine_spec.reference
56
+ StopMachine.call(action_handler: action_handler, auth_token: @auth_token, machine_spec: machine_spec)
57
+ end
58
+
59
+ def destroy_machine(action_handler, machine_spec, _machine_options)
60
+ return unless machine_spec.reference
61
+ DestroyMachine.call(action_handler: action_handler, auth_token: @auth_token, machine_spec: machine_spec)
62
+ end
63
+
64
+ def ready_machine(action_handler, machine_spec, machine_options)
65
+ ReadyMachine.call(auth_token: @auth_token, action_handler: action_handler, machine_spec: machine_spec)
66
+
67
+ machine_for(machine_spec, machine_options)
68
+ end
69
+
70
+ def machine_for(machine_spec, machine_options)
71
+ machine = GetMachine.call(auth_token: @auth_token, machine_spec: machine_spec).machine
72
+ ip_address = machine["ip_addresses"]["ip_address"].find do |address|
73
+ address["family"] == "IPv4" && address["access"] == "public"
74
+ end["address"]
75
+
76
+ ssh_options = {
77
+ auth_methods: ["password"],
78
+ password: machine_spec.reference["bootstrap_password"]
79
+ }
80
+
81
+ transport = Chef::Provisioning::Transport::SSH.new(
82
+ ip_address, "root", ssh_options, {}, config
83
+ )
84
+
85
+ convergence_strategy =
86
+ Chef::Provisioning::ConvergenceStrategy::InstallCached.new(machine_options[:convergence_options], {})
87
+ Chef::Provisioning::Machine::UnixMachine.new(machine_spec, transport, convergence_strategy)
88
+ end
89
+
90
+ def connect_to_machine(machine_spec, machine_options)
91
+ machine_for(machine_spec, machine_options)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,7 @@
1
+ class Chef
2
+ module Provisioning
3
+ module UpcloudDriver
4
+ VERSION = '0.2.0'
5
+ end
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,146 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chef-provisioning-upcloud
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Szymon Szypulski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: chef
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '12.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '12.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: chef-provisioning
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.5.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.5.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: hurley
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: interactor
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Provisioner for creating upcloud containers in Chef Provisioning.
98
+ email: szymon.szypulski@gmail.com
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - CHANGELOG.md
104
+ - README.md
105
+ - Rakefile
106
+ - lib/chef/provisioning/driver_init/upcloud.rb
107
+ - lib/chef/provisioning/interactors/base.rb
108
+ - lib/chef/provisioning/interactors/base/destroy_machine.rb
109
+ - lib/chef/provisioning/interactors/base/get_machine.rb
110
+ - lib/chef/provisioning/interactors/base/initialize_client.rb
111
+ - lib/chef/provisioning/interactors/base/ready_machine.rb
112
+ - lib/chef/provisioning/interactors/base/request_machine.rb
113
+ - lib/chef/provisioning/interactors/base/stop_machine.rb
114
+ - lib/chef/provisioning/interactors/destroy_machine.rb
115
+ - lib/chef/provisioning/interactors/get_machine.rb
116
+ - lib/chef/provisioning/interactors/ready_machine.rb
117
+ - lib/chef/provisioning/interactors/request_machine.rb
118
+ - lib/chef/provisioning/interactors/stop_machine.rb
119
+ - lib/chef/provisioning/upcloud_driver.rb
120
+ - lib/chef/provisioning/upcloud_driver/driver.rb
121
+ - lib/chef/provisioning/upcloud_driver/version.rb
122
+ homepage: https://github.com/szymonpk/chef-provisioning-upcloud
123
+ licenses:
124
+ - MIT
125
+ metadata: {}
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubyforge_project:
142
+ rubygems_version: 2.4.3
143
+ signing_key:
144
+ specification_version: 4
145
+ summary: Provisioner for creating upcloud containers in Chef Provisioning.
146
+ test_files: []