Merge branch 'CID-472_sync_autoscaling_groups' into qa
This commit is contained in:
commit
0286b3175d
@ -61,11 +61,14 @@ class Stack < Handler
|
|||||||
attrs[:tags] = JSON.parse(File.read(tags_filepath))
|
attrs[:tags] = JSON.parse(File.read(tags_filepath))
|
||||||
end
|
end
|
||||||
|
|
||||||
json = JSON.pretty_generate(
|
attrs.merge!(
|
||||||
without_bootstrap: options[:without_bootstrap] || false,
|
launch_options: {
|
||||||
skip_rollback: options[:skip_rollback] || false,
|
without_bootstrap: options[:without_bootstrap] || false,
|
||||||
stack_attributes: attrs
|
skip_rollback: options[:skip_rollback] || false,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
json = JSON.pretty_generate(attrs)
|
||||||
if question(I18n.t("handler.stack.question.create")) {puts json}
|
if question(I18n.t("handler.stack.question.create")) {puts json}
|
||||||
job_ids = post_body "/stack", json
|
job_ids = post_body "/stack", json
|
||||||
reports_urls(job_ids)
|
reports_urls(job_ids)
|
||||||
|
|||||||
@ -20,18 +20,13 @@ module Devops
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create_stack
|
def create_stack
|
||||||
object = parser.create
|
stack_attrs = parser.create
|
||||||
stack_attrs = object['stack_attributes']
|
|
||||||
project = Devops::Db.connector.project(stack_attrs['project'])
|
project = Devops::Db.connector.project(stack_attrs['project'])
|
||||||
env = project.deploy_env(stack_attrs['deploy_env'])
|
env = project.deploy_env(stack_attrs['deploy_env'])
|
||||||
raise InvalidRecord.new("Environment '#{env.identifier}' of project '#{project.id}' has no stack template") if env.stack_template.nil?
|
raise InvalidRecord.new("Environment '#{env.identifier}' of project '#{project.id}' has no stack template") if env.stack_template.nil?
|
||||||
add_stack_attributes(stack_attrs, env, parser)
|
add_stack_attributes(stack_attrs, env, parser)
|
||||||
|
|
||||||
jid = Worker.start_async(StackBootstrapWorker,
|
jid = Worker.start_async(StackBootstrapWorker, stack_attributes: stack_attrs)
|
||||||
stack_attributes: stack_attrs,
|
|
||||||
without_bootstrap: object['without_bootstrap'],
|
|
||||||
skip_rollback: object['skip_rollback']
|
|
||||||
)
|
|
||||||
[jid]
|
[jid]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -7,21 +7,10 @@ module Devops
|
|||||||
|
|
||||||
def create
|
def create
|
||||||
@body ||= create_object_from_json_body
|
@body ||= create_object_from_json_body
|
||||||
|
project_name = check_string(@body["project"], "Parameter 'project' must be a not empty string")
|
||||||
# temp fix to work on qa:
|
env_name = check_string(@body["deploy_env"], "Parameter 'deploy_env' must be a not empty string")
|
||||||
unless @body['stack_attributes']
|
check_string(@body["name"], "Parameter 'name' must be a not empty string", true, false)
|
||||||
@body = {
|
list = check_array(@body["run_list"], "Parameter 'run_list' is invalid, it should be not empty array of strings", String, true, true)
|
||||||
'stack_attributes' => @body.dup,
|
|
||||||
'without_bootstrap' => true,
|
|
||||||
'skip_rollback' => true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
stack_attributes = @body.fetch('stack_attributes')
|
|
||||||
project_name = check_string(stack_attributes["project"], "Parameter 'project' must be a not empty string")
|
|
||||||
env_name = check_string(stack_attributes["deploy_env"], "Parameter 'deploy_env' must be a not empty string")
|
|
||||||
check_string(stack_attributes["name"], "Parameter 'name' must be a not empty string", true, false)
|
|
||||||
list = check_array(stack_attributes["run_list"], "Parameter 'run_list' is invalid, it should be not empty array of strings", String, true, true)
|
|
||||||
Validators::Helpers::RunList.new(list).validate! unless list.nil?
|
Validators::Helpers::RunList.new(list).validate! unless list.nil?
|
||||||
@body
|
@body
|
||||||
end
|
end
|
||||||
|
|||||||
@ -30,19 +30,19 @@ module Devops
|
|||||||
# - Content-Type: application/json
|
# - Content-Type: application/json
|
||||||
# - body :
|
# - body :
|
||||||
# {
|
# {
|
||||||
# "stack_attributes": {
|
# "project": "project_name",
|
||||||
# "project": "project_name",
|
# "deploy_env": "test",
|
||||||
# "deploy_env": "test",
|
# "provider": "ec2",
|
||||||
# "provider": "ec2",
|
# "tags": {
|
||||||
# "tags": {
|
# "tagName": "tagValue"
|
||||||
# "tagName": "tagValue"
|
# },
|
||||||
# },
|
# "parameters": {
|
||||||
# "parameters": {
|
# "KeyName": "Value"
|
||||||
# "KeyName": "Value"
|
# },
|
||||||
# }
|
# "launch_options": {
|
||||||
|
# "without_bootstrap": false,
|
||||||
|
# "skip_rollback": false
|
||||||
# }
|
# }
|
||||||
# "without_bootstrap": false,
|
|
||||||
# "skip_rollback": false
|
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
# * *Returns* :
|
# * *Returns* :
|
||||||
|
|||||||
@ -8,6 +8,7 @@ module Devops
|
|||||||
include ModelWithProvider
|
include ModelWithProvider
|
||||||
|
|
||||||
attr_accessor :parameters, :events, :stack_status, :persisting_is_locked
|
attr_accessor :parameters, :events, :stack_status, :persisting_is_locked
|
||||||
|
attr_accessor :launch_options # {'without_bootstrap' => false, 'skip_rollback' => true}
|
||||||
|
|
||||||
set_field_validators :id, [::Validators::FieldValidator::NotNil,
|
set_field_validators :id, [::Validators::FieldValidator::NotNil,
|
||||||
::Validators::FieldValidator::FieldType::String,
|
::Validators::FieldValidator::FieldType::String,
|
||||||
@ -57,6 +58,7 @@ module Devops
|
|||||||
self.tags = attrs['tags'] || {}
|
self.tags = attrs['tags'] || {}
|
||||||
self.stack_status = attrs['stack_status']
|
self.stack_status = attrs['stack_status']
|
||||||
self.persisting_is_locked = attrs['persisting_is_locked']
|
self.persisting_is_locked = attrs['persisting_is_locked']
|
||||||
|
self.launch_options = attrs['launch_options'] || {}
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -72,7 +74,8 @@ module Devops
|
|||||||
owner: owner,
|
owner: owner,
|
||||||
run_list: run_list,
|
run_list: run_list,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
persisting_is_locked: persisting_is_locked
|
persisting_is_locked: persisting_is_locked,
|
||||||
|
launch_options: launch_options
|
||||||
}.merge(provider_hash)
|
}.merge(provider_hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -96,15 +99,6 @@ module Devops
|
|||||||
self.stack_status = 'NOT_FOUND'
|
self.stack_status = 'NOT_FOUND'
|
||||||
end
|
end
|
||||||
|
|
||||||
def resources
|
|
||||||
provider_instance.stack_resources(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
# resource_id is logical
|
|
||||||
def resource(resource_id)
|
|
||||||
provider_instance.stack_resource(self, resource_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def template_body
|
def template_body
|
||||||
stack_template_model.template_body
|
stack_template_model.template_body
|
||||||
end
|
end
|
||||||
@ -123,6 +117,14 @@ module Devops
|
|||||||
Devops::Db.connector.unlock_persisting_stack(id)
|
Devops::Db.connector.unlock_persisting_stack(id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def without_bootstrap?
|
||||||
|
launch_options['without_bootstrap'] || false
|
||||||
|
end
|
||||||
|
|
||||||
|
def skip_rollback?
|
||||||
|
launch_options['skip_rollback'] || false
|
||||||
|
end
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
|
|
||||||
# attrs should include:
|
# attrs should include:
|
||||||
|
|||||||
@ -31,8 +31,7 @@ en:
|
|||||||
server_bootstrap_private_ip_unset: "Server '%{server_id}' deploy failed: private ip is unset (job %{job_id})."
|
server_bootstrap_private_ip_unset: "Server '%{server_id}' deploy failed: private ip is unset (job %{job_id})."
|
||||||
deploy_unknown_error: "Unknown error occured during server '%{server_id}' deploy (job %{job_id})."
|
deploy_unknown_error: "Unknown error occured during server '%{server_id}' deploy (job %{job_id})."
|
||||||
deploy_failed: "Server '%{server_id}' deploy failed (job %{job_id})."
|
deploy_failed: "Server '%{server_id}' deploy failed (job %{job_id})."
|
||||||
creating_server_unknown_error: "Unknown error occured during server '%{server_id}' creation (job %{job_id})."
|
unknown_error: "Unknown error occured during server '%{server_id}' bootstrap or deploy (job %{job_id})."
|
||||||
creating_server_in_cloud_failed: "Server '%{server_id}' creation in cloud failed (job %{job_id})."
|
|
||||||
stack_creation_waiter:
|
stack_creation_waiter:
|
||||||
result:
|
result:
|
||||||
ok: |
|
ok: |
|
||||||
|
|||||||
@ -0,0 +1,14 @@
|
|||||||
|
db.stacks.update(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
$set: {
|
||||||
|
launch_options: {
|
||||||
|
without_bootstrap: false,
|
||||||
|
skip_rollback: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
multi: true
|
||||||
|
}
|
||||||
|
)
|
||||||
@ -279,10 +279,6 @@ module Provider
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def stack_resources(stack)
|
|
||||||
cloud_formation.describe_stack_resources({'StackName' => stack.name}).body['StackResources']
|
|
||||||
end
|
|
||||||
|
|
||||||
def stack_events(stack)
|
def stack_events(stack)
|
||||||
cloud_formation.describe_stack_events(stack.name).body['StackEvents'].map{|se| {"timestamp" => se["Timestamp"], "stack_name" => se["StackName"], "stack_id" => se["StackId"], "event_id" => se["EventId"], "reason" => se["ResourceStatusReason"], "status" => se["ResourceStatus"]}}.sort{|se1, se2| se1["timestamp"] <=> se2["timestamp"]}
|
cloud_formation.describe_stack_events(stack.name).body['StackEvents'].map{|se| {"timestamp" => se["Timestamp"], "stack_name" => se["StackName"], "stack_id" => se["StackId"], "event_id" => se["EventId"], "reason" => se["ResourceStatusReason"], "status" => se["ResourceStatus"]}}.sort{|se1, se2| se1["timestamp"] <=> se2["timestamp"]}
|
||||||
end
|
end
|
||||||
|
|||||||
@ -10,6 +10,7 @@ FactoryGirl.define do
|
|||||||
name 'iamstack'
|
name 'iamstack'
|
||||||
owner 'root'
|
owner 'root'
|
||||||
run_list []
|
run_list []
|
||||||
|
launch_options({})
|
||||||
|
|
||||||
initialize_with { new(attributes.stringify_keys) }
|
initialize_with { new(attributes.stringify_keys) }
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,7 @@ RSpec.describe Devops::Model::StackEc2, type: :model do
|
|||||||
|
|
||||||
describe '#to_hash_without_id' do
|
describe '#to_hash_without_id' do
|
||||||
it 'returns hash with several fields' do
|
it 'returns hash with several fields' do
|
||||||
expect(stack.to_hash_without_id.keys).to include('provider', :project, :deploy_env, :stack_template, :name, :owner, :run_list, :tags)
|
expect(stack.to_hash_without_id.keys).to include('provider', :project, :deploy_env, :stack_template, :name, :owner, :run_list, :tags, :launch_options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -52,6 +52,37 @@ RSpec.describe Devops::Model::StackEc2, type: :model do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'without_bootstrap?' do
|
||||||
|
it 'returns set falsey value' do
|
||||||
|
stack = described_class.new('launch_options' => {'without_bootstrap' => false})
|
||||||
|
expect(stack.without_bootstrap?).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns set truthy value' do
|
||||||
|
stack = described_class.new('launch_options' => {'without_bootstrap' => true})
|
||||||
|
expect(stack.without_bootstrap?).to be true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false by default' do
|
||||||
|
expect(described_class.new.without_bootstrap?).to be false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'skip_rollback?' do
|
||||||
|
it 'returns set falsey value' do
|
||||||
|
stack = described_class.new('launch_options' => {'skip_rollback' => false})
|
||||||
|
expect(stack.skip_rollback?).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns set truthy value' do
|
||||||
|
stack = described_class.new('launch_options' => {'skip_rollback' => true})
|
||||||
|
expect(stack.skip_rollback?).to be true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false by default' do
|
||||||
|
expect(described_class.new.skip_rollback?).to be false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#create_stack_in_cloud!' do
|
describe '#create_stack_in_cloud!' do
|
||||||
it 'calls create_stack method of provider instance' do
|
it 'calls create_stack method of provider instance' do
|
||||||
|
|||||||
@ -5,11 +5,13 @@ RSpec.describe StackBootstrapWorker, type: :worker, stubbed_connector: true, ini
|
|||||||
let(:stack_attrs) { attributes_for(:stack_ec2).stringify_keys }
|
let(:stack_attrs) { attributes_for(:stack_ec2).stringify_keys }
|
||||||
let(:worker) { described_class.new }
|
let(:worker) { described_class.new }
|
||||||
let(:perform_with_bootstrap) { worker.perform('stack_attributes' => stack_attrs) }
|
let(:perform_with_bootstrap) { worker.perform('stack_attributes' => stack_attrs) }
|
||||||
let(:perform_without_bootstrap) { worker.perform('stack_attributes' => stack_attrs, 'without_bootstrap' => true) }
|
let(:perform_without_bootstrap) {
|
||||||
|
set_without_bootstrap_to(true)
|
||||||
|
worker.perform('stack_attributes' => stack_attrs)
|
||||||
|
}
|
||||||
let(:executor) {
|
let(:executor) {
|
||||||
instance_double(Devops::Executor::StackExecutor,
|
instance_double(Devops::Executor::StackExecutor,
|
||||||
wait_till_stack_is_created: true,
|
wait_till_stack_is_created: true,
|
||||||
create_stack: Devops::Model::StackEc2.new(stack_attrs),
|
|
||||||
persist_new_servers: nil,
|
persist_new_servers: nil,
|
||||||
delete_stack: nil,
|
delete_stack: nil,
|
||||||
bootstrap_just_persisted: bootstrap_result(:ok)
|
bootstrap_just_persisted: bootstrap_result(:ok)
|
||||||
@ -20,10 +22,20 @@ RSpec.describe StackBootstrapWorker, type: :worker, stubbed_connector: true, ini
|
|||||||
Devops::Executor::StackExecutor::PrioritizedGroupsBootstrapper::Result.from_reason(reason)
|
Devops::Executor::StackExecutor::PrioritizedGroupsBootstrapper::Result.from_reason(reason)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_without_bootstrap_to(value)
|
||||||
|
stack_attrs.merge!('launch_options' => {'without_bootstrap' => value})
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_skip_rollback_to(value)
|
||||||
|
stack_attrs.merge!('launch_options' => {'skip_rollback' => value})
|
||||||
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(worker).to receive(:update_report)
|
allow(worker).to receive(:update_report)
|
||||||
allow(worker).to receive(:executor) { executor }
|
allow(worker).to receive(:executor) { executor }
|
||||||
allow(stubbed_connector).to receive(:unlock_persisting_stack)
|
allow(stubbed_connector).to receive(:unlock_persisting_stack)
|
||||||
|
# #create_stack should be lazy evaluated because stack_attrs may change
|
||||||
|
allow(executor).to receive(:create_stack) { Devops::Model::StackEc2.new(stack_attrs) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -64,16 +76,29 @@ RSpec.describe StackBootstrapWorker, type: :worker, stubbed_connector: true, ini
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'if without_bootstrap is false or not set' do
|
context 'if without_bootstrap is false' do
|
||||||
it 'returns 0 when bootstraping servers was successful' do
|
it 'returns 0 when bootstraping servers was successful' do
|
||||||
expect(perform_with_bootstrap).to eq 0
|
expect(perform_with_bootstrap).to eq 0
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'rollbacks stack and returns 1 when a known error occured during servers bootstrap' do
|
context "when a known error occured during servers bootstrap" do
|
||||||
allow(executor).to receive(:bootstrap_just_persisted) { bootstrap_result(:bootstrap_error) }
|
before do
|
||||||
expect(executor).to receive(:delete_stack)
|
allow(executor).to receive(:bootstrap_just_persisted) { bootstrap_result(:bootstrap_error) }
|
||||||
perform_with_bootstrap
|
end
|
||||||
expect(perform_with_bootstrap).to eq 1
|
|
||||||
|
it 'rollbacks stack and returns 1 if skip_rollback is false' do
|
||||||
|
set_skip_rollback_to(false)
|
||||||
|
expect(executor).to receive(:delete_stack)
|
||||||
|
perform_with_bootstrap
|
||||||
|
expect(perform_with_bootstrap).to eq 1
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't rollback stack, but returns 1 if skip_rollback is true" do
|
||||||
|
set_skip_rollback_to(true)
|
||||||
|
expect(executor).not_to receive(:delete_stack)
|
||||||
|
perform_with_bootstrap
|
||||||
|
expect(perform_with_bootstrap).to eq 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't rollback stack and returns 2 when a known error occured during servers deploy" do
|
it "doesn't rollback stack and returns 2 when a known error occured during servers deploy" do
|
||||||
@ -82,11 +107,24 @@ RSpec.describe StackBootstrapWorker, type: :worker, stubbed_connector: true, ini
|
|||||||
expect(perform_with_bootstrap).to eq 2
|
expect(perform_with_bootstrap).to eq 2
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'rollbacks stack and reraises that error when an unknown error occured during servers bootsrap and deploy' do
|
context "when an unknown error occured during servers bootsrap and deploy" do
|
||||||
error = StandardError.new
|
let(:error) { StandardError.new }
|
||||||
allow(executor).to receive(:bootstrap_just_persisted) { raise error }
|
before do
|
||||||
expect(worker).to receive(:rollback_stack!)
|
allow(executor).to receive(:bootstrap_just_persisted) { raise error }
|
||||||
expect{perform_with_bootstrap}.to raise_error(error)
|
end
|
||||||
|
|
||||||
|
it 'rollbacks stack and reraises that error if skip_rollback is false' do
|
||||||
|
set_skip_rollback_to(false)
|
||||||
|
expect(worker).to receive(:rollback_stack!)
|
||||||
|
expect{perform_with_bootstrap}.to raise_error(error)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't rollback stack, but reraises that error if skip_rollback is true" do
|
||||||
|
set_skip_rollback_to(true)
|
||||||
|
expect(worker).not_to receive(:rollback_stack!)
|
||||||
|
expect{perform_with_bootstrap}.to raise_error(error)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -4,18 +4,16 @@ class StackBootstrapWorker < Worker
|
|||||||
|
|
||||||
# @options:
|
# @options:
|
||||||
# 'stack_attributes', required
|
# 'stack_attributes', required
|
||||||
# 'without_bootstrap', optional. false by default
|
|
||||||
# 'skip_rollback', optional. false by default
|
|
||||||
def perform(options)
|
def perform(options)
|
||||||
call do
|
call do
|
||||||
puts_and_flush JSON.pretty_generate(options)
|
puts_and_flush JSON.pretty_generate(options)
|
||||||
stack_attrs = options.fetch('stack_attributes')
|
stack_attrs = options.fetch('stack_attributes')
|
||||||
without_bootstrap = options['without_bootstrap'] || false
|
|
||||||
skip_rollback = options['skip_rollback'] || false
|
|
||||||
|
|
||||||
save_report(stack_attrs)
|
save_report(stack_attrs)
|
||||||
|
|
||||||
@stack = executor.create_stack(stack_attrs)
|
@stack = executor.create_stack(stack_attrs)
|
||||||
|
without_bootstrap = @stack.without_bootstrap?
|
||||||
|
skip_rollback = @stack.skip_rollback?
|
||||||
|
|
||||||
if !executor.wait_till_stack_is_created
|
if !executor.wait_till_stack_is_created
|
||||||
puts_and_flush "Stack creating error"
|
puts_and_flush "Stack creating error"
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user