update stack template presets: now you can actually create stacks

This commit is contained in:
Anton Chuchkalov 2015-07-08 19:42:36 +04:00
parent 356925de49
commit 6161e7f5e8
10 changed files with 57 additions and 122 deletions

View File

@ -46,19 +46,15 @@ class StackTemplatePreset < Handler
abort(wrong_params) abort(wrong_params)
end end
preset = @args[2] params = {}
provider = options[:provider] || resources_selector.select_available_provider params[:id] = @args[2]
stack_template_id_to_create = options[:stack_template] || enter_parameter(I18n.t('handler.stack_template_preset.create.stack_template')) params[:provider] = options[:provider] || resources_selector.select_available_provider
parameters = options[:parameters] || enter_hash(I18n.t('handler.stack_template_preset.create.parameters')) params[:stack] = options[:stack] || enter_parameter(I18n.t('handler.stack_template_preset.create.stack'))
params = { filepath = options[:parameters_file] || enter_parameter(I18n.t('handler.stack_template_preset.create.parameters_file'))
id: preset, params[:parameters] = JSON.parse(File.read(filepath))
provider: provider,
stack_template: stack_template_id_to_create,
parameters: parameters
}
result = post_body("/stack_template_presets/#{preset}/build_stack_template", JSON.pretty_generate(params)) result = post_body("/stack_template_presets/#{params[:id]}/build_stack_template", JSON.pretty_generate(params))
end end
end end

View File

@ -17,18 +17,9 @@ class StackTemplatePresetOptions < CommonOptions
self.options do |parser, options| self.options do |parser, options|
parser.banner << self.build_banner parser.banner << self.build_banner
parser.recognize_option_value(:provider, 'stack') parser.recognize_option_value(:provider, 'stack_template_preset')
parser.recognize_option_value(:stack_template, 'stack') parser.recognize_option_value(:stack, 'stack_template_preset')
parser.recognize_option_value(:parameters_file, 'stack_template_preset')
parser.recognize_option_value(:parameters, 'stack') do |parameters|
begin
hash = JSON.parse(parameters)
options[:parameters] = hash
rescue JSON::ParserError
raise ArgumentError.new('Should be proper JSON string')
end
end
end end
end end

View File

@ -120,7 +120,7 @@ en:
delete: "Are you sure to delete stack '%{name}'?" delete: "Are you sure to delete stack '%{name}'?"
stack_template_preset: stack_template_preset:
create: create:
parameters: Parameters hash as single quoted JSON string parameters_file: 'Path to file with JSON parameters: '
stack_template: 'Name of stack template to build: ' stack_template: 'Name of stack template to build: '
message: message:
choose_list_default: "Choose %{name} (comma separated), like 1,2,3 or empty for default value '%{default}': " choose_list_default: "Choose %{name} (comma separated), like 1,2,3 or empty for default value '%{default}': "
@ -377,5 +377,9 @@ en:
provider: Stack template provider provider: Stack template provider
id: Stack template id id: Stack template id
template_file: Stack template file template_file: Stack template file
stack_template_preset:
parameters_file: Path to file with JSON parameters
stack: 'Name of stack to build: '
provider: Stack provider
user: user:
new_password: New user password new_password: New user password

View File

@ -2,13 +2,14 @@ module Devops
module Model module Model
class StackBase < MongoModel class StackBase < MongoModel
attr_accessor :id, :project, :deploy_env, :stack_template, :cloud_stack_id, :provider, :parameters attr_accessor :id, :project, :deploy_env, :stack_template, :cloud_stack_id, :provider, :parameters, :template_body
types id: {type: String, empty: false}, types id: {type: String, empty: false},
provider: {type: String, empty: false}, provider: {type: String, empty: false},
project: {type: String, empty: false}, project: {type: String, empty: true},
deploy_env: {type: String, empty: false}, deploy_env: {type: String, empty: true},
stack_template: {type: String, empty: false} stack_template: {type: String, empty: true},
template_body: {type: String, empty: true}
# cloud_stack_id: {type: String, empty: true} # cloud_stack_id: {type: String, empty: true}
# TODO: add parameters Hash # TODO: add parameters Hash
@ -18,7 +19,8 @@ module Devops
self.project = attrs['project'] self.project = attrs['project']
self.deploy_env = attrs['deploy_env'] self.deploy_env = attrs['deploy_env']
self.stack_template = attrs['stack_template'] self.stack_template = attrs['stack_template']
self.cloud_stack_id = attrs['cloud_stack_id'] self.template_body = attrs['template_body']
# self.cloud_stack_id = attrs['cloud_stack_id']
self.parameters = attrs['parameters'] self.parameters = attrs['parameters']
self self
end end
@ -59,9 +61,11 @@ module Devops
raise 'override me' raise 'override me'
end end
# if not set in constructor, assume stack was created via stack_template.
# It is need to support presets.
# TODO: refactore it.
def template_body def template_body
stack_template_model = DevopsService.mongo.stack_template(stack_template) @template_body ||= DevopsService.mongo.stack_template(stack_template).template_body
stack_template_model.template_body
end end
end end

View File

@ -9,7 +9,7 @@ class DevopsConfig
class << self class << self
def read config_file=nil def read config_file=nil
if config_file.nil? if config_file.nil?
config_file = ENV["CONFIG"] || File.join(File.dirname(__FILE__), "config.rb") config_file = ENV['DEVOPS_CONFIG'] || ENV['CONFIG'] || File.join(File.dirname(__FILE__), 'config.rb')
end end
config = {:url_prefix => ""} config = {:url_prefix => ""}
if File.exists? config_file if File.exists? config_file

View File

@ -13,92 +13,23 @@ module Devops
{id: id, template_preset_body: template_preset_body} {id: id, template_preset_body: template_preset_body}
end end
def build_template_from_preset(provider, stack_template_id, template_attrs) def create_stack_from_preset(provider, stack_id, parameters)
stack_template_attrs = { stack_attrs = {
'id' => stack_template_id, 'id' => stack_id,
'provider' => provider, 'provider' => provider,
'template_body' => serialize(actual_template_hash(template_attrs)) 'parameters' => parameters,
'template_body' => template_preset_body
} }
template_model = Model::StackTemplateFactory.create(provider, stack_template_attrs) Model::StackFactory.create(provider, stack_attrs)
end end
def template_preset_body def template_preset_body
@template_preset_body ||= begin file_name = File.join("lib/stack_template_presets/#{id}.#{template_file_extension}")
file_name = File.join("lib/stack_template_presets/#{id}.#{template_file_extension}") File.read(file_name)
File.read(file_name)
end
end
private
def template_preset_hash
unserialize(template_preset_body)
end
def actual_template_hash(template_attrs)
actual = template_preset_hash.dup
template_attrs.each do |key, value|
path = param_attrs_pathes_in_preset[key.to_s]
next unless path
insert_value_at(actual, value, path)
end
actual
end
# returns hash with keys lists. Better to show an example:
# Imagine tha t template is the following:
# {
# template: {
# users_count: %users_count%
# }
# }
#
# So param_attrs_pathes_in_preset will be
# {users_count: [:template, :users_count]}
def param_attrs_pathes_in_preset
{}
end
# given hash = {t: {a: nil}}, value = 1, path = [:t, :a] returns
# {t: {a: 1}}
def insert_value_at(hash, value, path)
current = hash
path.each_with_index do |key, i|
if i == path.size - 1
current[key] = value
else
current = current[key]
end
end
hash
end end
# some templates may be YAML files # some templates may be YAML files
def template_file_extension def template_file_extension
serialization_strategy.to_s
end
# some templates may be YAML files
def serialize(hash)
case serialization_strategy
when :json
hash.to_json
else
raise
end
end
def unserialize(text)
case serialization_strategy
when :json
JSON.parse(text)
else
raise
end
end
def serialization_strategy
:json :json
end end

View File

@ -1,5 +0,0 @@
{
"template": {
"users_count": null
}
}

View File

@ -1,9 +1,7 @@
module Devops::StackTemplatePresets module Devops::StackTemplatePresets
class PostgresCluster < Base class PostgresCluster < Base
def param_attrs_pathes_in_preset def template_file_extension
{ :yml
'users_count' => %w(template users_count)
}
end end
end end
end end

View File

@ -0,0 +1,17 @@
heat_template_version: 2013-05-23
description: Simple template to deploy a single compute instance
parameters:
key_name:
type: string
label: Key Name
description: Name of key-pair to be used for compute instance
resources:
my_instance:
type: OS::Nova::Server
properties:
key_name: { get_param: key_name }
image: 227f4be7-be1c-498d-ab88-54f8b5df249f
flavor: m1.small

View File

@ -27,13 +27,12 @@ module Devops
attrs = create_object_from_json_body attrs = create_object_from_json_body
provider, stack_template, parameters = attrs.fetch('provider'), attrs.fetch('stack_template'), attrs.fetch('parameters') provider, stack_id, parameters = attrs.fetch('provider'), attrs.fetch('stack'), attrs.fetch('parameters')
preset = Devops::StackTemplatePresetsFactory.get(attrs.fetch('id')) preset = Devops::StackTemplatePresetsFactory.get(attrs.fetch('id'))
template_model = preset.build_template_from_preset(provider, stack_template, parameters) stack = preset.create_stack_from_preset(provider, stack_id, parameters)
settings.mongo.stack_template_insert(template_model) create_response 'Created', stack.to_hash, 201
create_response 'Created', template_model.to_hash, 201
} }
end end