require "db/mongo/models/model_with_provider" require "providers/exceptions/name_conflict" module Devops module Model class StackBase < MongoModel include ModelWithProvider 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, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty] set_field_validators :provider, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty] set_field_validators :project, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty] set_field_validators :deploy_env, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty] set_field_validators :stack_template, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty] set_field_validators :name, [::Validators::FieldValidator::Nil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty] set_field_validators :owner, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty] set_field_validators :run_list, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::Array, ::Validators::FieldValidator::RunList] set_field_validators :tags, [::Validators::FieldValidator::Nil, ::Validators::FieldValidator::FieldType::Hash] def initialize attrs={} self.set_provider(attrs) self.id = attrs['id'] self.project = attrs['project'] self.deploy_env = attrs['deploy_env'] self.stack_template = attrs['stack_template'] self.name = attrs['name'] self.parameters = attrs['parameters'] self.owner = attrs['owner'] self.run_list = attrs['run_list'] || [] self.tags = attrs['tags'] || {} self.stack_status = attrs['stack_status'] self.persisting_is_locked = attrs['persisting_is_locked'] self.launch_options = attrs['launch_options'] || {} self end # TODO: use string keys def to_hash_without_id { project: project, deploy_env: deploy_env, stack_template: stack_template, name: name, parameters: parameters, stack_status: stack_status, owner: owner, run_list: run_list, tags: tags, persisting_is_locked: persisting_is_locked, launch_options: launch_options }.merge(provider_hash) end def create_stack_in_cloud! out begin provider_instance.create_stack(self, out) rescue ProviderErrors::NameConflict raise InvalidRecord.new "Duplicate key error: stack with name '#{id}' already exists in cloud" end end def delete_stack_in_cloud! provider_instance.delete_stack(self) end def sync_status_and_events! self.stack_status = provider_instance.stack_details(self)[:stack_status] self.events = provider_instance.stack_events(self) rescue Fog::AWS::CloudFormation::NotFound self.stack_status = 'NOT_FOUND' end def template_body stack_template_model.template_body end def stack_template_model Devops::Db.connector.stack_template(stack_template) end def lock_persisting! self.persisting_is_locked = true Devops::Db.connector.lock_persisting_stack(id) end def unlock_persisting! self.persisting_is_locked = false Devops::Db.connector.unlock_persisting_stack(id) end def without_bootstrap? launch_options['without_bootstrap'] || false end def skip_rollback? result = launch_options['skip_rollback'] result.nil? ? true : result end class << self # attrs should include: # - id (String) # - deploy_env (String) # - stack_template (String) # - provider (String) # - provider_account (String) def create(attrs, out) model = new(attrs) model.create_stack_in_cloud!(out) model.sync_status_and_events! model end def build_from_bson(attrs) attrs['id'] = attrs["_id"] self.new(attrs) end end end end end