merge stack_templates and stacks on serverside
This commit is contained in:
parent
2a62786299
commit
634d5d6d1f
@ -12,6 +12,7 @@ require "devops-client/handler/helpers/http_utils"
|
||||
require "devops-client/handler/helpers/outputtable"
|
||||
require "devops-client/handler/helpers/resources_fetcher"
|
||||
require "devops-client/handler/helpers/resources_selector"
|
||||
require "devops-client/providers/providers"
|
||||
|
||||
class Handler
|
||||
|
||||
|
||||
21
devops-client/lib/devops-client/providers/providers.rb
Normal file
21
devops-client/lib/devops-client/providers/providers.rb
Normal file
@ -0,0 +1,21 @@
|
||||
module Providers
|
||||
Ec2 = 'ec2'
|
||||
Openstack = 'openstack'
|
||||
Static = 'static'
|
||||
|
||||
def self.available
|
||||
[Ec2, Openstack, Static]
|
||||
end
|
||||
|
||||
def self.functionalities
|
||||
{
|
||||
images: [Ec2, Openstack],
|
||||
stack_templates: [Ec2, Openstack],
|
||||
stacks: [Ec2, Openstack]
|
||||
}
|
||||
end
|
||||
|
||||
def self.has_functionality?(provider, functionality)
|
||||
functionalities.fetch(functionality).include?(provider.to_s)
|
||||
end
|
||||
end
|
||||
@ -2,14 +2,15 @@ module Devops
|
||||
module Model
|
||||
class StackBase < MongoModel
|
||||
|
||||
attr_accessor :id, :project, :deploy_env, :stack_template, :cloud_stack_id, :provider
|
||||
attr_accessor :id, :project, :deploy_env, :stack_template, :cloud_stack_id, :provider, :parameters
|
||||
|
||||
types id: {type: String, empty: false},
|
||||
provider: {type: String, empty: false},
|
||||
project: {type: String, empty: false},
|
||||
deploy_env: {type: String, empty: false},
|
||||
stack_template: {type: String, empty: false},
|
||||
cloud_stack_id: {type: String, empty: false}
|
||||
stack_template: {type: String, empty: false}
|
||||
# cloud_stack_id: {type: String, empty: true}
|
||||
# TODO: add parameters Hash
|
||||
|
||||
def initialize attrs={}
|
||||
self.id = attrs['id']
|
||||
@ -18,19 +19,22 @@ module Devops
|
||||
self.deploy_env = attrs['deploy_env']
|
||||
self.stack_template = attrs['stack_template']
|
||||
self.cloud_stack_id = attrs['cloud_stack_id']
|
||||
self.parameters = attrs['parameters']
|
||||
self
|
||||
end
|
||||
|
||||
def to_hash_without_id
|
||||
{
|
||||
provider: provider,
|
||||
project: self.project,
|
||||
deploy_env: self.deploy_env,
|
||||
stack_template: self.stack_template,
|
||||
cloud_stack_id: self.cloud_stack_id
|
||||
project: project,
|
||||
deploy_env: deploy_env,
|
||||
stack_template: stack_template,
|
||||
cloud_stack_id: cloud_stack_id,
|
||||
parameters: parameters
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
# attrs should include:
|
||||
# - id (String)
|
||||
# - provider (String)
|
||||
@ -51,6 +55,15 @@ module Devops
|
||||
raise 'override me'
|
||||
end
|
||||
|
||||
def delete_stack_in_cloud!
|
||||
raise 'override me'
|
||||
end
|
||||
|
||||
def template_body
|
||||
stack_template_model = DevopsService.mongo.stack_template(stack_template)
|
||||
stack_template_model.template_body
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -3,10 +3,17 @@ module Devops
|
||||
class StackOpenstack < StackBase
|
||||
|
||||
def create_stack_in_cloud!
|
||||
provider = ::Provider::ProviderFactory.get('openstack')
|
||||
provider.create_stack(self)
|
||||
# # create stack in Openstack
|
||||
# self.cloud_stack_id = '4c712026-dcd5-4664-90b8-0915494c1332'
|
||||
begin
|
||||
provider = Provider::ProviderFactory.get('openstack')
|
||||
self.cloud_stack_id = provider.create_stack(self)
|
||||
rescue ProviderErrors::NameConflict
|
||||
raise InvalidRecord.new "Duplicate key error: stack with name '#{self.id}' already exists in cloud"
|
||||
end
|
||||
end
|
||||
|
||||
def delete_stack_in_cloud!
|
||||
provider = Provider::ProviderFactory.get('openstack')
|
||||
provider.delete_stack(self)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -5,23 +5,15 @@ module Devops
|
||||
module Model
|
||||
class StackTemplateBase < MongoModel
|
||||
|
||||
attr_accessor :id, :template_url, :template_json, :provider
|
||||
|
||||
# Few words about template_url:
|
||||
# In Amazon Cloudformation the template file must be stored on an Amazon S3 bucket,
|
||||
# but for Openstack stacks it isn't neccessary (your may use local file).
|
||||
# I decided to enforce template_url strategy using in openstack to reach more common
|
||||
# interface between different providers' stack templates.
|
||||
attr_accessor :id, :template_body, :provider
|
||||
|
||||
types id: {type: String, empty: false},
|
||||
provider: {type: String, empty: false},
|
||||
template_json: {type: String, empty: false},
|
||||
template_url: {type: String, empty: false}
|
||||
template_body: {type: String, empty: false}
|
||||
|
||||
def initialize(attrs)
|
||||
self.id = attrs['id']
|
||||
self.template_json = attrs['template_json'].to_s
|
||||
self.template_url = attrs['template_url']
|
||||
self.template_body = attrs['template_body']
|
||||
self.provider = attrs['provider']
|
||||
self
|
||||
end
|
||||
@ -29,23 +21,15 @@ module Devops
|
||||
def to_hash_without_id
|
||||
{
|
||||
provider: provider,
|
||||
template_json: template_json,
|
||||
template_url: template_url
|
||||
template_body: template_body
|
||||
}
|
||||
end
|
||||
|
||||
# do not forget to destroy template files on template destroying
|
||||
def delete_template_file_from_storage
|
||||
raise 'Override me'
|
||||
end
|
||||
|
||||
# attrs should include:
|
||||
# - id (String)
|
||||
# - provider (String)
|
||||
# - template_json (String)
|
||||
# - template_body (String)
|
||||
def self.create(attrs)
|
||||
json = attrs['template_json']
|
||||
attrs['template_url'] = generate_template_file_and_upload_to_storage(attrs['id'], json)
|
||||
new(attrs)
|
||||
end
|
||||
|
||||
@ -54,24 +38,6 @@ module Devops
|
||||
self.new(attrs)
|
||||
end
|
||||
|
||||
class << self
|
||||
private
|
||||
|
||||
def generate_template_file_and_upload_to_storage(id, json)
|
||||
tempfile = Tempfile.new('foo')
|
||||
tempfile.write(json)
|
||||
secure_filename = "#{id}-#{SecureRandom.hex}.template"
|
||||
upload_file_to_storage(secure_filename, tempfile.path)
|
||||
ensure
|
||||
tempfile.close
|
||||
tempfile.unlink
|
||||
end
|
||||
|
||||
def upload_file_to_storage(filename, file_path)
|
||||
raise 'Override me'
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -2,16 +2,50 @@ module Devops
|
||||
module Model
|
||||
class StackTemplateEc2 < StackTemplateBase
|
||||
|
||||
# In Amazon Cloudformation the template file must be stored on an Amazon S3 bucket.
|
||||
attr_accessor :template_url
|
||||
|
||||
types template_url: {type: String, empty: false}
|
||||
|
||||
def initialize(attrs)
|
||||
self.template_url = attrs['template_url']
|
||||
super(attrs)
|
||||
end
|
||||
|
||||
def to_hash_without_id
|
||||
super.merge(template_url: template_url)
|
||||
end
|
||||
|
||||
def delete_template_file_from_storage
|
||||
raise 'Implement me'
|
||||
end
|
||||
|
||||
class << self
|
||||
|
||||
def create(attrs)
|
||||
template = attrs['template_body']
|
||||
attrs['template_url'] = generate_template_file_and_upload_to_storage(attrs['id'], template)
|
||||
super(attrs)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def upload_file_to_storage(filename, path)
|
||||
def generate_template_file_and_upload_to_storage(id, json)
|
||||
begin
|
||||
tempfile = Tempfile.new('foo')
|
||||
tempfile.write(json)
|
||||
tempfile.close
|
||||
secure_filename = "#{id}-#{SecureRandom.hex}.template"
|
||||
upload_file_to_storage(secure_filename, tempfile.path)
|
||||
ensure
|
||||
tempfile.unlink
|
||||
end
|
||||
end
|
||||
|
||||
def upload_file_to_storage(filename, file_path)
|
||||
"https://s3.amazonaws.com/#{filename}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -2,18 +2,6 @@ module Devops
|
||||
module Model
|
||||
class StackTemplateOpenstack < StackTemplateBase
|
||||
|
||||
def delete_template_file_from_storage
|
||||
raise 'Implement me'
|
||||
end
|
||||
|
||||
class << self
|
||||
private
|
||||
|
||||
def upload_file_to_storage(filename, path)
|
||||
"https://openstack_host/v1/my_account/#{filename}"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
require "fog"
|
||||
Dir["providers/exceptions/*.rb"].each {|file| require file }
|
||||
|
||||
module Provider
|
||||
class BaseProvider
|
||||
|
||||
5
devops-service/providers/exceptions/name_conflict.rb
Normal file
5
devops-service/providers/exceptions/name_conflict.rb
Normal file
@ -0,0 +1,5 @@
|
||||
module ProviderErrors
|
||||
class NameConflict < StandardError
|
||||
|
||||
end
|
||||
end
|
||||
@ -192,9 +192,22 @@ module Provider
|
||||
end
|
||||
|
||||
def create_stack(stack)
|
||||
byebug
|
||||
result = orchestration.create_stack(stack.id, {template_url: stack.template_url})
|
||||
begin
|
||||
response = orchestration.create_stack(stack.id, {
|
||||
template: stack.template_body,
|
||||
tenant_id: connection_options[:openstack_tenant],
|
||||
parameters: stack.parameters
|
||||
})
|
||||
response[:body]['stack']['id']
|
||||
rescue Excon::Errors::Conflict => e
|
||||
raise ProviderErrors::NameConflict
|
||||
end
|
||||
end
|
||||
|
||||
def delete_stack(stack)
|
||||
orchestration.delete_stack(stack.id, stack.cloud_stack_id)
|
||||
end
|
||||
|
||||
private
|
||||
def convert_groups list
|
||||
res = {}
|
||||
@ -217,7 +230,7 @@ module Provider
|
||||
end
|
||||
|
||||
def orchestration
|
||||
@connection ||= Fog::Orchestration::OpenStack.new(connection_options)
|
||||
@connection ||= Fog::Orchestration.new(connection_options)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -61,4 +61,12 @@ class Provider::Openstack
|
||||
]
|
||||
end
|
||||
|
||||
def create_stack(stack)
|
||||
'4c712026-dcd5-4664-90b8-0915494c1332'
|
||||
end
|
||||
|
||||
def delete_stack(stack)
|
||||
true
|
||||
end
|
||||
|
||||
end
|
||||
@ -18,6 +18,8 @@ require "routes/v2.0/server"
|
||||
require "routes/v2.0/script"
|
||||
require "routes/v2.0/status"
|
||||
require "routes/v2.0/bootstrap_templates"
|
||||
require "routes/v2.0/stack_template"
|
||||
require "routes/v2.0/stack"
|
||||
|
||||
require "routes/v2.0/handlers/provider"
|
||||
require "routes/v2.0/handlers/bootstrap_templates"
|
||||
@ -34,6 +36,8 @@ require "routes/v2.0/handlers/status"
|
||||
require "routes/v2.0/handlers/tag"
|
||||
require "routes/v2.0/handlers/user"
|
||||
require "routes/v2.0/handlers/server"
|
||||
require "routes/v2.0/handlers/stack_template"
|
||||
require "routes/v2.0/handlers/stack"
|
||||
require "routes/routes_container"
|
||||
|
||||
require "auth/devops_auth"
|
||||
@ -61,7 +65,9 @@ module Devops
|
||||
Devops::Version2_0::Routes::ServerRoutes,
|
||||
Devops::Version2_0::Routes::StatusRoutes,
|
||||
Devops::Version2_0::Routes::TagRoutes,
|
||||
Devops::Version2_0::Routes::DeployRoutes
|
||||
Devops::Version2_0::Routes::DeployRoutes,
|
||||
Devops::Version2_0::Routes::StackTemplateRoutes,
|
||||
Devops::Version2_0::Routes::StackRoutes
|
||||
]
|
||||
|
||||
def init
|
||||
|
||||
60
devops-service/routes/v2.0/handlers/stack.rb
Normal file
60
devops-service/routes/v2.0/handlers/stack.rb
Normal file
@ -0,0 +1,60 @@
|
||||
require 'db/mongo/models/stack/stack_factory'
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Stack
|
||||
|
||||
def self.get_stacks
|
||||
lambda {
|
||||
check_privileges("stack", "r")
|
||||
stacks = settings.mongo.stacks
|
||||
json stacks.map(&:to_hash)
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_stacks_for_provider
|
||||
lambda {
|
||||
check_privileges("stack", "r")
|
||||
check_provider(params[:provider])
|
||||
stacks = settings.mongo.stacks(params[:provider])
|
||||
json stacks.map(&:to_hash)
|
||||
}
|
||||
end
|
||||
|
||||
def self.create_stack
|
||||
lambda {
|
||||
check_privileges("stack", "w")
|
||||
|
||||
object = create_object_from_json_body
|
||||
stack_model = Model::StackFactory.create(object['provider'], object)
|
||||
settings.mongo.stack_insert(stack_model)
|
||||
|
||||
create_response "Created", stack_model.to_hash, 201
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_stack
|
||||
lambda {
|
||||
check_privileges("stack", "r")
|
||||
stack = settings.mongo.stack(params[:stack_id])
|
||||
json stack.to_hash
|
||||
}
|
||||
end
|
||||
|
||||
def self.delete_stack
|
||||
lambda {
|
||||
check_privileges("stack", "w")
|
||||
|
||||
stack = settings.mongo.stack(params[:stack_id])
|
||||
stack.delete_stack_in_cloud!
|
||||
settings.mongo.stack_delete(params[:stack_id])
|
||||
|
||||
create_response("Stack '#{params[:stack_id]}' has been removed")
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
57
devops-service/routes/v2.0/handlers/stack_template.rb
Normal file
57
devops-service/routes/v2.0/handlers/stack_template.rb
Normal file
@ -0,0 +1,57 @@
|
||||
require 'db/mongo/models/stack_template/stack_template_factory'
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class StackTemplate
|
||||
|
||||
def self.get_stack_templates
|
||||
lambda {
|
||||
check_privileges('stack_template', 'r')
|
||||
stack_templates = settings.mongo.stack_templates
|
||||
json stack_templates.map(&:to_hash)
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_stack_templates_for_provider
|
||||
lambda {
|
||||
check_privileges('stack_template', 'r')
|
||||
check_provider(params[:provider])
|
||||
stack_templates = settings.mongo.stack_templates(params[:provider])
|
||||
json stack_templates.map(&:to_hash)
|
||||
}
|
||||
end
|
||||
|
||||
def self.create_stack_template
|
||||
lambda {
|
||||
check_privileges('stack_template', 'w')
|
||||
|
||||
attrs = create_object_from_json_body
|
||||
template_model = Model::StackTemplateFactory.create(attrs['provider'], attrs)
|
||||
|
||||
settings.mongo.stack_template_insert(template_model)
|
||||
create_response 'Created', template_model.to_hash, 201
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_stack_template
|
||||
lambda {
|
||||
check_privileges('stack_template', 'r')
|
||||
stack_template = settings.mongo.stack_template(params[:stack_template_id])
|
||||
json stack_template.to_hash
|
||||
}
|
||||
end
|
||||
|
||||
def self.delete_stack_template
|
||||
lambda {
|
||||
check_privileges('stack_template', 'w')
|
||||
|
||||
settings.mongo.stack_template_delete params[:stack_template_id]
|
||||
create_response("Template '#{params[:stack_template_id]}' has been removed")
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
31
devops-service/routes/v2.0/stack.rb
Normal file
31
devops-service/routes/v2.0/stack.rb
Normal file
@ -0,0 +1,31 @@
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Routes
|
||||
module StackRoutes
|
||||
|
||||
def self.registered(app)
|
||||
app.after %r{\A/stack_template(/[\w]+)?\z} do
|
||||
statistic
|
||||
end
|
||||
|
||||
app.get_with_headers '/stacks', :headers => [:accept], &Devops::Version2_0::Handler::Stack.get_stacks
|
||||
|
||||
app.get_with_headers '/stacks/provider/:provider', :headers => [:accept], &Devops::Version2_0::Handler::Stack.get_stacks_for_provider
|
||||
|
||||
app.post_with_headers "/stack", :headers => [:accept], &Devops::Version2_0::Handler::Stack.create_stack
|
||||
|
||||
hash = {}
|
||||
|
||||
hash['GET'] = Devops::Version2_0::Handler::Stack.get_stack
|
||||
|
||||
hash['DELETE'] = Devops::Version2_0::Handler::Stack.delete_stack
|
||||
|
||||
app.multi_routes '/stack/:stack_id', {}, hash
|
||||
|
||||
puts "Stack routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
31
devops-service/routes/v2.0/stack_template.rb
Normal file
31
devops-service/routes/v2.0/stack_template.rb
Normal file
@ -0,0 +1,31 @@
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Routes
|
||||
module StackTemplateRoutes
|
||||
|
||||
def self.registered(app)
|
||||
app.after %r{\A/stack_template(/[\w]+)?\z} do
|
||||
statistic
|
||||
end
|
||||
|
||||
app.get_with_headers '/stack_templates', :headers => [:accept], &Devops::Version2_0::Handler::StackTemplate.get_stack_templates
|
||||
|
||||
app.get_with_headers '/stack_templates/provider/:provider', :headers => [:accept], &Devops::Version2_0::Handler::StackTemplate.get_stack_templates_for_provider
|
||||
|
||||
app.post_with_headers "/stack_template", :headers => [:accept], &Devops::Version2_0::Handler::StackTemplate.create_stack_template
|
||||
|
||||
hash = {}
|
||||
|
||||
hash['GET'] = Devops::Version2_0::Handler::StackTemplate.get_stack_template
|
||||
|
||||
hash['DELETE'] = Devops::Version2_0::Handler::StackTemplate.delete_stack_template
|
||||
|
||||
app.multi_routes '/stack_template/:stack_template_id', {}, hash
|
||||
|
||||
puts "Stack_template routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue
Block a user