require "db/mongo/models/model_with_provider" require "providers/exceptions/name_conflict" module Devops module Model class StackBase < MongoModel include ModelWithProvider attr_accessor :id, :name, :project, :deploy_env, :stack_template, :parameters, :details, :owner, :run_list types id: {type: String, empty: false}, provider: {type: String, empty: false}, project: {type: String}, deploy_env: {type: String}, stack_template: {type: String, empty: false}, name: {type: String, nil: true}, owner: {type: String}, run_list: {type: Array, value_type: String, empty: true, nil: true} # details: {type: Hash, nil: true} # Hash type isn't supported yet def initialize attrs={} # self.provider = self.class.provider 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.details = attrs['details'] self.owner = attrs['owner'] self.run_list = attrs['run_list'] || [] self end def to_hash_without_id { project: project, deploy_env: deploy_env, stack_template: stack_template, name: name, parameters: parameters, # details are required to proper status handling details: bson_safe_details, stack_status: stack_status, owner: owner }.merge(provider_hash) end # overrided in ec2 def bson_safe_details details 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_details! self.details = provider_instance.stack_details(self) 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 # there is only one way to update stack status right now: # stack.sync_details! # mongo.stack_update(stack) # It's because syncing updates @details instance variable, but doesn'not persist it. # Also that's why we need to have "details" key in #to_mongo_hash def stack_status raise 'override me' end def stack_statuses # maybe they differ in different providers, so use method instead of hardcoding { in_progress: 'CREATE_IN_PROGRESS', complete: 'CREATE_COMPLETE' } end def template_body Devops::Db.connector.stack_template(stack_template).template_body 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_details! model end def build_from_bson(attrs) attrs['id'] = attrs["_id"] self.new(attrs) end end end end end