vagrant-aliyun 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +111 -0
- data/README.md +36 -0
- data/Rakefile +15 -0
- data/example_box/README.md +8 -0
- data/example_box/dummy_aliyun.box +0 -0
- data/example_box/metadata.json +3 -0
- data/lib/vagrant-aliyun/action/is_created.rb +18 -0
- data/lib/vagrant-aliyun/action/is_stopped.rb +18 -0
- data/lib/vagrant-aliyun/action/message_already_created.rb +16 -0
- data/lib/vagrant-aliyun/action/message_not_created.rb +16 -0
- data/lib/vagrant-aliyun/action/message_will_not_destroy.rb +16 -0
- data/lib/vagrant-aliyun/action/read_ssh_info.rb +38 -0
- data/lib/vagrant-aliyun/action/read_state.rb +47 -0
- data/lib/vagrant-aliyun/action/run_instance.rb +100 -0
- data/lib/vagrant-aliyun/action/start_instance.rb +90 -0
- data/lib/vagrant-aliyun/action/stop_instance.rb +52 -0
- data/lib/vagrant-aliyun/action/terminate_instance.rb +51 -0
- data/lib/vagrant-aliyun/action/wait_for_state.rb +41 -0
- data/lib/vagrant-aliyun/action/warn_networks.rb +19 -0
- data/lib/vagrant-aliyun/action.rb +182 -0
- data/lib/vagrant-aliyun/config.rb +55 -0
- data/lib/vagrant-aliyun/errors.rb +24 -0
- data/lib/vagrant-aliyun/plugin.rb +73 -0
- data/lib/vagrant-aliyun/provider.rb +50 -0
- data/lib/vagrant-aliyun/util/timer.rb +17 -0
- data/lib/vagrant-aliyun/version.rb +5 -0
- data/lib/vagrant-aliyun.rb +18 -0
- data/locales/en.yml +96 -0
- data/pkg/vagrant-aliyun-0.0.1.gem +0 -0
- data/pkg/vagrant-aliyun-0.0.2.gem +0 -0
- data/vagrant-aliyun.gemspec +52 -0
- metadata +76 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require 'json'
|
3
|
+
require "aliyun"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module AliyunECS
|
7
|
+
module Action
|
8
|
+
# This runs the configured instance.
|
9
|
+
class StartInstance
|
10
|
+
|
11
|
+
def initialize(app, env)
|
12
|
+
@app = app
|
13
|
+
@logger = Log4r::Logger.new("vagrant_aliyun::action::start_instance")
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
start_instance(env[:machine], env)
|
18
|
+
|
19
|
+
@app.call(env)
|
20
|
+
end
|
21
|
+
|
22
|
+
def start_instance(machine, env)
|
23
|
+
return nil if machine.id.nil?
|
24
|
+
|
25
|
+
config = machine.provider_config
|
26
|
+
options = {
|
27
|
+
:access_key_id => config.access_key_id,
|
28
|
+
:access_key_secret => config.access_key_secret
|
29
|
+
}
|
30
|
+
Aliyun.config options
|
31
|
+
ecs = Aliyun::ECS.new
|
32
|
+
|
33
|
+
env[:ui].info(I18n.t("vagrant_aliyun.starting"))
|
34
|
+
ecs.start_instance :instance_id=>machine.id
|
35
|
+
|
36
|
+
# Wait for the instance to be ready first
|
37
|
+
env[:ui].info(I18n.t("vagrant_aliyun.waiting_for_ready"))
|
38
|
+
begin
|
39
|
+
instance = ecs.describe_instance_attribute :instance_id=>machine.id
|
40
|
+
Timeout.timeout(config.instance_ready_timeout) do
|
41
|
+
until instance["Status"] == "Running"
|
42
|
+
sleep 2
|
43
|
+
instance = ecs.describe_instance_attribute :instance_id=>machine.id
|
44
|
+
end
|
45
|
+
end
|
46
|
+
rescue Timeout::Error
|
47
|
+
env[:result] = false # couldn't reach state in time
|
48
|
+
# Delete the instance
|
49
|
+
terminate(env)
|
50
|
+
|
51
|
+
# Notify the user
|
52
|
+
raise Errors::InstanceReadyTimeout,
|
53
|
+
timeout: config.instance_ready_timeout
|
54
|
+
end
|
55
|
+
|
56
|
+
if !env[:interrupted]
|
57
|
+
# Wait for SSH to be ready.
|
58
|
+
env[:ui].info(I18n.t("vagrant_aliyun.waiting_for_ssh"))
|
59
|
+
network_ready_retries = 0
|
60
|
+
network_ready_retries_max = 10
|
61
|
+
while true
|
62
|
+
# If we're interrupted then just back out
|
63
|
+
break if env[:interrupted]
|
64
|
+
# When an ECS instance comes up, it's networking may not be ready
|
65
|
+
# by the time we connect.
|
66
|
+
begin
|
67
|
+
break if env[:machine].communicate.ready?
|
68
|
+
rescue Exception => e
|
69
|
+
if network_ready_retries < network_ready_retries_max then
|
70
|
+
network_ready_retries += 1
|
71
|
+
@logger.warn(I18n.t("vagrant_aliyun.waiting_for_ssh, retrying"))
|
72
|
+
else
|
73
|
+
raise e
|
74
|
+
end
|
75
|
+
end
|
76
|
+
sleep 2
|
77
|
+
end
|
78
|
+
|
79
|
+
# Ready and booted!
|
80
|
+
env[:ui].info(I18n.t("vagrant_aliyun.ready"))
|
81
|
+
end
|
82
|
+
|
83
|
+
# Terminate the instance if we were interrupted
|
84
|
+
terminate(env) if env[:interrupted]
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module AliyunECS
|
5
|
+
module Action
|
6
|
+
# This stops the running instance.
|
7
|
+
class StopInstance
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@logger = Log4r::Logger.new("vagrant_aliyun::action::stop_instance")
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
stop_instance(env[:machine], env)
|
15
|
+
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
def stop_instance(machine, env)
|
20
|
+
return nil if machine.id.nil?
|
21
|
+
|
22
|
+
config = machine.provider_config
|
23
|
+
options = {
|
24
|
+
:access_key_id => config.access_key_id,
|
25
|
+
:access_key_secret => config.access_key_secret
|
26
|
+
}
|
27
|
+
Aliyun.config options
|
28
|
+
ecs = Aliyun::ECS.new
|
29
|
+
|
30
|
+
if machine.state.id == :stopped
|
31
|
+
env[:ui].info(I18n.t("vagrant_aliyun.already_status", :status => machine.state.id))
|
32
|
+
else
|
33
|
+
env[:ui].info(I18n.t("vagrant_aliyun.stopping"))
|
34
|
+
ecs.stop_instance :instance_id=>machine.id
|
35
|
+
begin
|
36
|
+
instance = ecs.describe_instance_attribute :instance_id=>machine.id
|
37
|
+
Timeout.timeout(config.instance_ready_timeout) do
|
38
|
+
until instance["Status"] == "Stopped"
|
39
|
+
sleep 2
|
40
|
+
instance = ecs.describe_instance_attribute :instance_id=>machine.id
|
41
|
+
end
|
42
|
+
end
|
43
|
+
rescue Timeout::Error
|
44
|
+
env[:result] = false # couldn't reach state in time
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module AliyunECS
|
5
|
+
module Action
|
6
|
+
# This stops the running instance.
|
7
|
+
class TerminateInstance
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@logger = Log4r::Logger.new("vagrant_aliyun::action::terminate_instance")
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
terminate_instance(env[:machine], env)
|
15
|
+
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
def terminate_instance(machine, env)
|
20
|
+
return nil if machine.id.nil?
|
21
|
+
|
22
|
+
config = machine.provider_config
|
23
|
+
options = {
|
24
|
+
:access_key_id => config.access_key_id,
|
25
|
+
:access_key_secret => config.access_key_secret
|
26
|
+
}
|
27
|
+
Aliyun.config options
|
28
|
+
ecs = Aliyun::ECS.new
|
29
|
+
|
30
|
+
env[:ui].info(I18n.t("vagrant_aliyun.terminating"))
|
31
|
+
ecs.stop_instance :instance_id=>machine.id
|
32
|
+
|
33
|
+
begin
|
34
|
+
instance = ecs.describe_instance_attribute :instance_id=>machine.id
|
35
|
+
Timeout.timeout(config.instance_ready_timeout) do
|
36
|
+
until instance["Status"] == "Stopped"
|
37
|
+
sleep 2
|
38
|
+
instance = ecs.describe_instance_attribute :instance_id=>machine.id
|
39
|
+
end
|
40
|
+
end
|
41
|
+
rescue Timeout::Error
|
42
|
+
env[:result] = false # couldn't reach state in time
|
43
|
+
end
|
44
|
+
|
45
|
+
ecs.delete_instance :instance_id=>machine.id
|
46
|
+
machine.id = nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require "timeout"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module AliyunECS
|
6
|
+
module Action
|
7
|
+
# This action will wait for a machine to reach a specific state or quit by timeout
|
8
|
+
class WaitForState
|
9
|
+
# env[:result] will be false in case of timeout.
|
10
|
+
# @param [Symbol] state Target machine state.
|
11
|
+
# @param [Number] timeout Timeout in seconds.
|
12
|
+
def initialize(app, env, state, timeout)
|
13
|
+
@app = app
|
14
|
+
@logger = Log4r::Logger.new("vagrant_aliyun::action::wait_for_state")
|
15
|
+
@state = state
|
16
|
+
@timeout = timeout
|
17
|
+
end
|
18
|
+
|
19
|
+
def call(env)
|
20
|
+
env[:result] = true
|
21
|
+
if env[:machine].state.id == @state
|
22
|
+
@logger.info(I18n.t("vagrant_aliyun.already_status", :status => @state))
|
23
|
+
else
|
24
|
+
@logger.info("Waiting for machine to reach state #{@state}")
|
25
|
+
begin
|
26
|
+
Timeout.timeout(@timeout) do
|
27
|
+
until env[:machine].state.id == @state
|
28
|
+
sleep 2
|
29
|
+
end
|
30
|
+
end
|
31
|
+
rescue Timeout::Error
|
32
|
+
env[:result] = false # couldn't reach state in time
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
@app.call(env)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module AliyunECS
|
3
|
+
module Action
|
4
|
+
class WarnNetworks
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
if env[:machine].config.vm.networks.length > 0
|
11
|
+
env[:ui].warn(I18n.t("vagrant_aliyun.warn_networks"))
|
12
|
+
end
|
13
|
+
|
14
|
+
@app.call(env)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
require "pathname"
|
2
|
+
require "aliyun"
|
3
|
+
require "vagrant/action/builder"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module AliyunECS
|
7
|
+
module Action
|
8
|
+
# Include the built-in modules so we can use them as top-level things.
|
9
|
+
include Vagrant::Action::Builtin
|
10
|
+
|
11
|
+
# This action is called to halt the remote machine.
|
12
|
+
def self.action_halt
|
13
|
+
Vagrant::Action::Builder.new.tap do |b|
|
14
|
+
b.use ConfigValidate
|
15
|
+
b.use Call, IsCreated do |env, b2|
|
16
|
+
if !env[:result]
|
17
|
+
b2.use MessageNotCreated
|
18
|
+
next
|
19
|
+
end
|
20
|
+
|
21
|
+
b2.use StopInstance
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# This action is called to terminate the remote machine.
|
27
|
+
def self.action_destroy
|
28
|
+
Vagrant::Action::Builder.new.tap do |b|
|
29
|
+
b.use Call, DestroyConfirm do |env, b2|
|
30
|
+
if env[:result]
|
31
|
+
b2.use ConfigValidate
|
32
|
+
b2.use Call, IsCreated do |env2, b3|
|
33
|
+
if !env2[:result]
|
34
|
+
b3.use MessageNotCreated
|
35
|
+
next
|
36
|
+
end
|
37
|
+
b3.use TerminateInstance
|
38
|
+
b3.use ProvisionerCleanup if defined?(ProvisionerCleanup)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
b2.use MessageWillNotDestroy
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# This action is called when `vagrant provision` is called.
|
48
|
+
def self.action_provision
|
49
|
+
Vagrant::Action::Builder.new.tap do |b|
|
50
|
+
b.use ConfigValidate
|
51
|
+
b.use Call, IsCreated do |env, b2|
|
52
|
+
if !env[:result]
|
53
|
+
b2.use MessageNotCreated
|
54
|
+
next
|
55
|
+
end
|
56
|
+
|
57
|
+
b2.use Provision
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# This action is called to read the SSH info of the machine. The
|
63
|
+
# resulting state is expected to be put into the `:machine_ssh_info`
|
64
|
+
# key.
|
65
|
+
def self.action_read_ssh_info
|
66
|
+
Vagrant::Action::Builder.new.tap do |b|
|
67
|
+
b.use ConfigValidate
|
68
|
+
b.use ReadSSHInfo
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# This action is called to read the state of the machine. The
|
73
|
+
# resulting state is expected to be put into the `:machine_state_id`
|
74
|
+
# key.
|
75
|
+
def self.action_read_state
|
76
|
+
Vagrant::Action::Builder.new.tap do |b|
|
77
|
+
b.use ConfigValidate
|
78
|
+
b.use ReadState
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# This action is called to SSH into the machine.
|
83
|
+
def self.action_ssh
|
84
|
+
Vagrant::Action::Builder.new.tap do |b|
|
85
|
+
b.use ConfigValidate
|
86
|
+
b.use Call, IsCreated do |env, b2|
|
87
|
+
if !env[:result]
|
88
|
+
b2.use MessageNotCreated
|
89
|
+
next
|
90
|
+
end
|
91
|
+
|
92
|
+
b2.use SSHExec
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.action_ssh_run
|
98
|
+
Vagrant::Action::Builder.new.tap do |b|
|
99
|
+
b.use ConfigValidate
|
100
|
+
b.use Call, IsCreated do |env, b2|
|
101
|
+
if !env[:result]
|
102
|
+
b2.use MessageNotCreated
|
103
|
+
next
|
104
|
+
end
|
105
|
+
|
106
|
+
b2.use SSHRun
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.action_prepare_boot
|
112
|
+
Vagrant::Action::Builder.new.tap do |b|
|
113
|
+
b.use Provision
|
114
|
+
b.use SyncedFolders
|
115
|
+
b.use WarnNetworks
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# This action is called to bring the box up from nothing.
|
120
|
+
def self.action_up
|
121
|
+
Vagrant::Action::Builder.new.tap do |b|
|
122
|
+
b.use HandleBox
|
123
|
+
b.use ConfigValidate
|
124
|
+
b.use BoxCheckOutdated
|
125
|
+
b.use Call, IsCreated do |env1, b1|
|
126
|
+
if env1[:result]
|
127
|
+
b1.use Call, IsStopped do |env2, b2|
|
128
|
+
if env2[:result]
|
129
|
+
b2.use action_prepare_boot
|
130
|
+
b2.use StartInstance # restart this instance
|
131
|
+
else
|
132
|
+
b2.use MessageAlreadyCreated # TODO write a better message
|
133
|
+
end
|
134
|
+
end
|
135
|
+
else
|
136
|
+
b1.use action_prepare_boot
|
137
|
+
b1.use RunInstance # launch a new instance
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.action_reload
|
144
|
+
Vagrant::Action::Builder.new.tap do |b|
|
145
|
+
b.use ConfigValidate
|
146
|
+
b.use Call, IsCreated do |env, b2|
|
147
|
+
if !env[:result]
|
148
|
+
b2.use MessageNotCreated
|
149
|
+
next
|
150
|
+
end
|
151
|
+
|
152
|
+
b2.use action_halt
|
153
|
+
b2.use Call, WaitForState, :stopped, 120 do |env2, b3|
|
154
|
+
if env2[:result]
|
155
|
+
b3.use action_up
|
156
|
+
else
|
157
|
+
# TODO we couldn't reach :stopped, what now?
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# The autoload farm
|
165
|
+
action_root = Pathname.new(File.expand_path("../action", __FILE__))
|
166
|
+
autoload :IsCreated, action_root.join("is_created")
|
167
|
+
autoload :IsStopped, action_root.join("is_stopped")
|
168
|
+
autoload :MessageAlreadyCreated, action_root.join("message_already_created")
|
169
|
+
autoload :MessageNotCreated, action_root.join("message_not_created")
|
170
|
+
autoload :MessageWillNotDestroy, action_root.join("message_will_not_destroy")
|
171
|
+
autoload :ReadSSHInfo, action_root.join("read_ssh_info")
|
172
|
+
autoload :ReadState, action_root.join("read_state")
|
173
|
+
autoload :RunInstance, action_root.join("run_instance")
|
174
|
+
autoload :StartInstance, action_root.join("start_instance")
|
175
|
+
autoload :StopInstance, action_root.join("stop_instance")
|
176
|
+
autoload :TerminateInstance, action_root.join("terminate_instance")
|
177
|
+
autoload :WaitForState, action_root.join("wait_for_state")
|
178
|
+
autoload :WarnNetworks, action_root.join("warn_networks")
|
179
|
+
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module AliyunECS
|
5
|
+
class Config < Vagrant.plugin("2", :config)
|
6
|
+
|
7
|
+
attr_accessor :access_key_id
|
8
|
+
attr_accessor :access_key_secret
|
9
|
+
attr_accessor :region_id
|
10
|
+
attr_accessor :image_id
|
11
|
+
attr_accessor :instance_type
|
12
|
+
attr_accessor :internet_max_bandwidth_out
|
13
|
+
attr_accessor :security_group_id
|
14
|
+
attr_accessor :password
|
15
|
+
attr_accessor :instance_ready_timeout
|
16
|
+
|
17
|
+
def initialize()
|
18
|
+
@access_key_id = UNSET_VALUE
|
19
|
+
@access_key_secret = UNSET_VALUE
|
20
|
+
@region_id = UNSET_VALUE
|
21
|
+
@image_id = UNSET_VALUE
|
22
|
+
@instance_type = UNSET_VALUE
|
23
|
+
@internet_max_bandwidth_out = UNSET_VALUE
|
24
|
+
@security_group_id = UNSET_VALUE
|
25
|
+
@password = UNSET_VALUE
|
26
|
+
@instance_ready_timeout = UNSET_VALUE
|
27
|
+
end
|
28
|
+
|
29
|
+
def finalize!
|
30
|
+
@access_key_id = nil if @access_key_id == UNSET_VALUE
|
31
|
+
@access_key_secret = nil if @access_key_secret == UNSET_VALUE
|
32
|
+
@region_id = nil if @region_id == UNSET_VALUE
|
33
|
+
@image_id = nil if @image_id == UNSET_VALUE
|
34
|
+
@instance_type = nil if @instance_type == UNSET_VALUE
|
35
|
+
@internet_max_bandwidth_out = nil if @internet_max_bandwidth_out == UNSET_VALUE
|
36
|
+
@security_group_id = nil if @security_group_id == UNSET_VALUE
|
37
|
+
@password = nil if @password == UNSET_VALUE
|
38
|
+
@instance_ready_timeout = 120 if @instance_ready_timeout == UNSET_VALUE
|
39
|
+
end
|
40
|
+
|
41
|
+
def validate(machine)
|
42
|
+
errors = _detected_errors
|
43
|
+
errors << I18n.t("vagrant_aliyun.config.access_key_id_required") if @access_key_id.nil?
|
44
|
+
errors << I18n.t("vagrant_aliyun.config.access_key_secret_required") if @access_key_secret.nil?
|
45
|
+
errors << I18n.t("vagrant_aliyun.config.region_id_required") if @region_id.nil?
|
46
|
+
errors << I18n.t("vagrant_aliyun.config.image_id_required") if @image_id.nil?
|
47
|
+
errors << I18n.t("vagrant_aliyun.config.instance_type_required") if @instance_type.nil?
|
48
|
+
errors << I18n.t("vagrant_aliyun.config.internet_max_bandwidth_out_required") if @internet_max_bandwidth_out.nil?
|
49
|
+
errors << I18n.t("vagrant_aliyun.config.security_group_id_required") if @security_group_id.nil?
|
50
|
+
errors << I18n.t("vagrant_aliyun.config.password_required") if @password.nil?
|
51
|
+
{ "Aliyun Provider" => errors }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|