Last active
December 14, 2017 15:06
-
-
Save chewmanfoo/e0fd89674902ac24484b9dff7b35df4d to your computer and use it in GitHub Desktop.
cf_deployment.rb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/models/cf_deployment.rb | |
# env:string, account:string, delay:string, deploy_at:datetime, revision:string, branch:string, tag:string | |
class CfDeployment < ApplicationRecord | |
WORKPATH = "/tmp/plp1" | |
progname = "app/models/cf_deployment.rb" | |
# model association | |
belongs_to :cf_template | |
belongs_to :creator, :class_name => 'User' | |
#has_one :qk_deployment | |
attr_reader :deployment_path, :region, :files, :local_path | |
# callbacks | |
before_save { | |
@region = "us-east-1" | |
setup_services | |
@stack_name = @ns.name_cloudformation_stack | |
} | |
after_create { | |
setup_repo | |
setup_params | |
validate_artifacts | |
start_deployment | |
#estimate_stack_cost | |
} | |
before_destroy { | |
@region = "us-east-1" | |
setup_services | |
@stack_name = @ns.name_cloudformation_stack | |
} | |
after_destroy { | |
delete_stack | |
} | |
# validations | |
# :revision and _branch are not required fields | |
# if they are not present, we use HEAD on master | |
validates_presence_of :env, :account | |
validates_presence_of :deploy_at, if: Proc.new {|a| a.delay?} | |
# TODO these environments are also repeated in the credentials service - DRY | |
validates_inclusion_of :env, :in => %w( cit_certification cit_production ec_sandbox ) | |
# TODO these accounts are also repeated in the credentials service - DRY | |
validates_inclusion_of :account, :in => %w( 234740779720 415334768129 163158673736 ) | |
validates_inclusion_of :key, :in => User.all.map{|e| e.key} | |
# delegation | |
delegate :repo, :path, :nested, :parent_filename, :manifest_filename, | |
to: :cf_template, prefix: true | |
def delay? | |
delay == "true" | |
end | |
def dry_run? | |
dry_run == "true" | |
end | |
def template_buckets | |
{"ec_sandbox" => "sabre-sbx-templates", "cit_certification" => "sabre.templates", "cit_production" => "sabre-templates"} | |
end | |
# workflow | |
# deployment has a workflow - | |
# :preflight transitions to :start with | |
# :start transitions to :running with | |
# :running transitions to :complete with ; transitions to :failed with | |
# :complete transitions to :retire with | |
# :failed transitions to :retire with | |
# :retire done | |
# temporary functions | |
def setup_repo | |
args={repo: cf_template_repo, path: cf_template_path, workpath: WORKPATH, | |
nested: cf_template_nested, branch: branch, revision: revision, tag: tag} | |
@gs = GitService.new(args) | |
@local_path = @gs.get_repo | |
@files = @gs.get_file_list | |
end | |
def setup_services | |
args={env: env, cf_template_filename: cf_template_parent_filename, include_suffix: false} | |
@ns = NamingService.new(args) | |
args={environment: env, method: "env"} | |
@cs = AwsCredentialsService.new(args) | |
args={creds: @cs.creds, region: region, arn: @cs.arn} | |
@s3 = AwsS3Service.new(args) | |
args={creds: @cs.creds, arn: @cs.arn, region: region} | |
@cfs = AwsCloudFormationService.new(args) | |
end | |
def setup_params | |
end | |
def validate_artifacts | |
logger.info "got files: #{files}" | |
files.select{|e| e.include?(".json")}.each do |template_file| | |
s3url = @s3.put_local_file_in_s3({local_path: local_path, file_name: template_file, bucket: template_buckets[env]}) | |
resp = @cfs.validate_template({url: s3url, arn: @cs.arn, region: region}) | |
logger.info "resp: #{resp}" | |
#TODO what to do if any are invalid!! | |
end | |
end | |
def start_deployment | |
stack_name = @ns.name_cloudformation_stack | |
params = @cfs.convert_manifest_to_params({path: "#{local_path}#{cf_template_manifest_filename}", | |
file: cf_template_parent_filename, env: env, format: "internal"}) | |
logger.info "got params!: #{params}" | |
s3url = @s3.get_file_url({filename: cf_template_parent_filename, bucket: template_buckets[env]}) | |
@cfs.create_stack({url: s3url, arn: @cs.arn, stack_name: stack_name, region: region, params: params, dry_run: dry_run}) | |
######################################################################################### | |
#TODO: this SHOULD BE asynchronous - need a out-of-band runner to execute this! | |
# this might timeout before it finishes | |
end | |
def delete_stack | |
stack_name = @ns.name_cloudformation_stack | |
if @cfs.stack_exists?({stack_name: stack_name, dry_run: dry_run}) | |
@cfs.delete_stack({stack_name: stack_name, dry_run: dry_run}) | |
else | |
logger.info "app/models/cf_deployment.rb #delete_stack - asked to delete stack called #{stack_name}, but stack does not exist! Skipping." | |
end | |
end | |
def estimate_stack_cost | |
stack_name = @ns.name_cloudformation_stack | |
params = @cfs.convert_manifest_to_params({path: "#{local_path}#{cf_template_manifest_filename}", | |
file: cf_template_parent_filename, env: env}) | |
#p "got params!: #{params}" | |
s3url = @s3.get_file_url({filename: cf_template_parent_filename, bucket: template_buckets[env]}) | |
@cost_url = @cfs.estimate_stack_cost({url: s3url, arn: @cs.arn, stack_name: stack_name, region: region, params: params}) | |
######################################################################################### | |
#TODO: this SHOULD BE asynchronous - need a out-of-band runner to execute this! | |
# this might timeout before it finishes | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ActiveRecord::Schema.define(version: 20171214002124) do | |
# These are extensions that must be enabled in order to support this database | |
enable_extension "plpgsql" | |
create_table "cf_deployments", force: :cascade do |t| | |
t.string "env" | |
t.string "account" | |
t.datetime "deploy_at" | |
t.integer "cf_template_id" | |
t.datetime "created_at", null: false | |
t.datetime "updated_at", null: false | |
t.string "delay" | |
t.string "revision" | |
t.string "branch" | |
t.string "tag" | |
t.string "dry_run" | |
t.string "cost_url" | |
t.string "stack_name" | |
t.integer "creator_id" | |
t.index ["cf_template_id"], name: "index_cf_deployments_on_cf_template_id", using: :btree | |
end | |
create_table "cf_templates", force: :cascade do |t| | |
t.string "repo" | |
t.string "path" | |
t.datetime "created_at", null: false | |
t.datetime "updated_at", null: false | |
t.string "nested" | |
t.integer "creator_id" | |
end | |
create_table "qk_deployments", force: :cascade do |t| | |
t.integer "cf_template_id" | |
t.integer "cf_deployment_id" | |
t.datetime "created_at", null: false | |
t.datetime "updated_at", null: false | |
t.index ["cf_deployment_id"], name: "index_qk_deployments_on_cf_deployment_id", using: :btree | |
t.index ["cf_template_id"], name: "index_qk_deployments_on_cf_template_id", using: :btree | |
end | |
create_table "users", force: :cascade do |t| | |
t.string "name" | |
t.string "key" | |
t.datetime "created_at", null: false | |
t.datetime "updated_at", null: false | |
end | |
add_foreign_key "cf_deployments", "cf_templates" | |
add_foreign_key "qk_deployments", "cf_deployments" | |
add_foreign_key "qk_deployments", "cf_templates" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment