diff --git a/devops-client/lib/devops-client/handler/handler_factory.rb b/devops-client/lib/devops-client/handler/handler_factory.rb index 03ac0a4..e1f9d9c 100644 --- a/devops-client/lib/devops-client/handler/handler_factory.rb +++ b/devops-client/lib/devops-client/handler/handler_factory.rb @@ -47,6 +47,9 @@ class HandlerFactory when "stack_template" require "devops-client/handler/stack_template" StackTemplate + when "stack_template_preset" + require "devops-client/handler/stack_template_preset" + StackTemplatePreset when "stack" require "devops-client/handler/stack" Stack diff --git a/devops-client/lib/devops-client/handler/stack_template_preset.rb b/devops-client/lib/devops-client/handler/stack_template_preset.rb new file mode 100644 index 0000000..5c95925 --- /dev/null +++ b/devops-client/lib/devops-client/handler/stack_template_preset.rb @@ -0,0 +1,40 @@ +require "devops-client/handler/handler" +require "devops-client/options/stack_template_preset_options" +require "devops-client/output/stack_template_preset" +# require 'devops-client/helpers/select_available' + +class StackTemplatePreset < Handler + + output_with Output::StackTemplatePreset + + def initialize(host, def_options={}) + @host, @options = host, def_options + @options_parser = StackTemplatePresetOptions.new(ARGV, def_options) + end + + def handle + @options, @args = @options_parser.parse_options_for!(current_command) + case current_command + when :list + list_handler + output + when :show + show_handler + output + end + end + + def show_handler + r = inspect_parameters @options_parser.show_params, @args[2] + unless r.nil? + @options_parser.invalid_show_command + abort(r) + end + @show = get "/stack_template_presets/#{@args[2]}" + end + + def list_handler + @list = get("/stack_template_presets") + end + +end diff --git a/devops-client/lib/devops-client/options/stack_template_preset_options.rb b/devops-client/lib/devops-client/options/stack_template_preset_options.rb new file mode 100644 index 0000000..6f13137 --- /dev/null +++ b/devops-client/lib/devops-client/options/stack_template_preset_options.rb @@ -0,0 +1,22 @@ +require "devops-client/options/common_options" + +class StackTemplatePresetOptions < CommonOptions + + commands :list, :show + + def initialize args, def_options + super(args, def_options) + self.header = I18n.t("headers.stack_template_preset") + self.banner_header = "stack_template_preset" + self.list_params = ["[provider]", "[ec2|openstack]"] + self.show_params = ["STACK"] + end + + + extend_options_method :list_options do |options| + if args[2] + options[:given_provider] = args[2] + end + end + +end diff --git a/devops-client/lib/devops-client/output/stack_template_preset.rb b/devops-client/lib/devops-client/output/stack_template_preset.rb new file mode 100644 index 0000000..6e61349 --- /dev/null +++ b/devops-client/lib/devops-client/output/stack_template_preset.rb @@ -0,0 +1,40 @@ +require "devops-client/output/base" + +module Output + class StackTemplatePreset < Base + + def table + if outputting_list? + title = I18n.t("output.title.stack_template_preset.list") + headers, rows = create_list + create_table headers, rows, title, with_num? + else + @data["id"] + "\n" + @data["template_preset_body"] + end + end + + def csv + if outputting_list? + headers, rows = create_list + else + headers, rows = create_show + end + create_csv headers, rows, with_num? + end + + def json + JSON.pretty_generate(@data) + end + + private + + def create_list + abort(I18n.t("output.not_found.stack_template_preset.list")) if @data.empty? + + fields_to_output = %w(id) + + headers_and_rows(@data, fields_to_output) + end + + end +end diff --git a/devops-client/locales/en.yml b/devops-client/locales/en.yml index 49fc21e..b0fa640 100644 --- a/devops-client/locales/en.yml +++ b/devops-client/locales/en.yml @@ -43,6 +43,7 @@ en: user: "User" stack: "Stack" stack_template: "Stack template" + stack_template_preset: "Stack template preset" handler: flavor: list: @@ -188,6 +189,7 @@ en: created_by: "Created by" template_url: "Template url" template_body: "Template body" + template_preset_body: "Template preset body" stack_template: "Stack Template" cloud_stack_id: "Cloud Stack id" title: @@ -228,6 +230,9 @@ en: stack_template: list: "Stack Templates" show: "Stack Template" + stack_template_preset: + list: "Stack Template Presets" + show: "Stack Template Preset" stack: list: "Stacks" show: "Stack" @@ -262,6 +267,9 @@ en: stack_template: list: "No stack templates found" show: "There isn't such stack template" + stack_template_preset: + list: "No stack template presets found" + show: "There isn't such stack template preset" stack: list: "No stacks found" show: "There isn't such stack" diff --git a/devops-service/lib/stack_template_presets/base.rb b/devops-service/lib/stack_template_presets/base.rb new file mode 100644 index 0000000..fa0917a --- /dev/null +++ b/devops-service/lib/stack_template_presets/base.rb @@ -0,0 +1,26 @@ +require 'lib/string_helper' + +module Devops + module StackTemplatePresets + class Base + + def id + StringHelper.underscore_class(self.class) + end + + def to_hash + {id: id, template_preset_body: template_preset_body} + end + + def template_preset_body + file_name = File.join("lib/stack_template_presets/#{id}.json") + File.read(file_name) + end + + def build_template_from_preset(provider, options={}) + # do smth + end + + end + end +end \ No newline at end of file diff --git a/devops-service/lib/stack_template_presets/factory.rb b/devops-service/lib/stack_template_presets/factory.rb new file mode 100644 index 0000000..2feaeae --- /dev/null +++ b/devops-service/lib/stack_template_presets/factory.rb @@ -0,0 +1,20 @@ +require_relative 'base' +require_relative 'postgres_cluster' + +class Devops::StackTemplatePresetsFactory + + # find all classes in Devops::StackTemplatePresets modules excluding Base and factory. + # This list can be extended in external gems via defining new classes in Devops::StackTemplatePresets module. + def self.list + @list ||= Devops::StackTemplatePresets.constants.select do |class_name| + class_name != :Base + end.map do |class_name| + Devops::StackTemplatePresets.const_get(class_name).new + end + end + + def self.get(id) + list.detect { |preset| preset.id == id } + end + +end \ No newline at end of file diff --git a/devops-service/lib/stack_template_presets/postgres_cluster.json b/devops-service/lib/stack_template_presets/postgres_cluster.json new file mode 100644 index 0000000..a02461a --- /dev/null +++ b/devops-service/lib/stack_template_presets/postgres_cluster.json @@ -0,0 +1,137 @@ +{ + "AWSTemplateFormatVersion" : "2010-09-09", + + "Description" : "AWS CloudFormation Sample Template EC2InstanceWithSecurityGroupSample: Create an Amazon EC2 instance running the Amazon Linux AMI. The AMI is chosen based on the region in which the stack is run. This example creates an EC2 security group for the instance to give you SSH access. **WARNING** This template creates an Amazon EC2 instance. You will be billed for the AWS resources used if you create a stack from this template.", + + "Parameters" : { + "KeyName": { + "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instance", + "Type": "AWS::EC2::KeyPair::KeyName", + "ConstraintDescription" : "must be the name of an existing EC2 KeyPair." + }, + + "InstanceType" : { + "Description" : "WebServer EC2 instance type", + "Type" : "String", + "Default" : "m1.small", + "AllowedValues" : [ "t1.micro", "t2.micro", "t2.small", "t2.medium", "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "m3.medium", "m3.large", "m3.xlarge", "m3.2xlarge", "c1.medium", "c1.xlarge", "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "g2.2xlarge", "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "hi1.4xlarge", "hs1.8xlarge", "cr1.8xlarge", "cc2.8xlarge", "cg1.4xlarge"] +, + "ConstraintDescription" : "must be a valid EC2 instance type." + }, + + "SSHLocation" : { + "Description" : "The IP address range that can be used to SSH to the EC2 instances", + "Type": "String", + "MinLength": "9", + "MaxLength": "18", + "Default": "0.0.0.0/0", + "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", + "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x." + } + }, + + "Mappings" : { + "AWSInstanceType2Arch" : { + "t1.micro" : { "Arch" : "PV64" }, + "t2.micro" : { "Arch" : "HVM64" }, + "t2.small" : { "Arch" : "HVM64" }, + "t2.medium" : { "Arch" : "HVM64" }, + "m1.small" : { "Arch" : "PV64" }, + "m1.medium" : { "Arch" : "PV64" }, + "m1.large" : { "Arch" : "PV64" }, + "m1.xlarge" : { "Arch" : "PV64" }, + "m2.xlarge" : { "Arch" : "PV64" }, + "m2.2xlarge" : { "Arch" : "PV64" }, + "m2.4xlarge" : { "Arch" : "PV64" }, + "m3.medium" : { "Arch" : "HVM64" }, + "m3.large" : { "Arch" : "HVM64" }, + "m3.xlarge" : { "Arch" : "HVM64" }, + "m3.2xlarge" : { "Arch" : "HVM64" }, + "c1.medium" : { "Arch" : "PV64" }, + "c1.xlarge" : { "Arch" : "PV64" }, + "c3.large" : { "Arch" : "HVM64" }, + "c3.xlarge" : { "Arch" : "HVM64" }, + "c3.2xlarge" : { "Arch" : "HVM64" }, + "c3.4xlarge" : { "Arch" : "HVM64" }, + "c3.8xlarge" : { "Arch" : "HVM64" }, + "c4.large" : { "Arch" : "HVM64" }, + "c4.xlarge" : { "Arch" : "HVM64" }, + "c4.2xlarge" : { "Arch" : "HVM64" }, + "c4.4xlarge" : { "Arch" : "HVM64" }, + "c4.8xlarge" : { "Arch" : "HVM64" }, + "g2.2xlarge" : { "Arch" : "HVMG2" }, + "r3.large" : { "Arch" : "HVM64" }, + "r3.xlarge" : { "Arch" : "HVM64" }, + "r3.2xlarge" : { "Arch" : "HVM64" }, + "r3.4xlarge" : { "Arch" : "HVM64" }, + "r3.8xlarge" : { "Arch" : "HVM64" }, + "i2.xlarge" : { "Arch" : "HVM64" }, + "i2.2xlarge" : { "Arch" : "HVM64" }, + "i2.4xlarge" : { "Arch" : "HVM64" }, + "i2.8xlarge" : { "Arch" : "HVM64" }, + "hi1.4xlarge" : { "Arch" : "HVM64" }, + "hs1.8xlarge" : { "Arch" : "HVM64" }, + "cr1.8xlarge" : { "Arch" : "HVM64" }, + "cc2.8xlarge" : { "Arch" : "HVM64" } + } +, + "AWSRegionArch2AMI" : { + "us-east-1" : {"PV64" : "ami-50311038", "HVM64" : "ami-5231103a", "HVMG2" : "ami-8c6b40e4"}, + "us-west-2" : {"PV64" : "ami-5d79546d", "HVM64" : "ami-43795473", "HVMG2" : "ami-abbe919b"}, + "us-west-1" : {"PV64" : "ami-eb4fa8af", "HVM64" : "ami-f74fa8b3", "HVMG2" : "ami-f31ffeb7"}, + "eu-west-1" : {"PV64" : "ami-a71588d0", "HVM64" : "ami-a51588d2", "HVMG2" : "ami-d5bc24a2"}, + "eu-central-1" : {"PV64" : "ami-ac5c61b1", "HVM64" : "ami-a25c61bf", "HVMG2" : "ami-7cd2ef61"}, + "ap-northeast-1" : {"PV64" : "ami-8d1df78d", "HVM64" : "ami-a51df7a5", "HVMG2" : "ami-6318e863"}, + "ap-southeast-1" : {"PV64" : "ami-887041da", "HVM64" : "ami-5e73420c", "HVMG2" : "ami-3807376a"}, + "ap-southeast-2" : {"PV64" : "ami-bb1e6e81", "HVM64" : "ami-ad1e6e97", "HVMG2" : "ami-89790ab3"}, + "sa-east-1" : {"PV64" : "ami-29aa1234", "HVM64" : "ami-27aa123a", "HVMG2" : "NOT_SUPPORTED"}, + "cn-north-1" : {"PV64" : "ami-503aa869", "HVM64" : "ami-543aa86d", "HVMG2" : "NOT_SUPPORTED"} + } + + }, + + "Resources" : { + "EC2Instance" : { + "Type" : "AWS::EC2::Instance", + "Properties" : { + "InstanceType" : { "Ref" : "InstanceType" }, + "SecurityGroups" : [ { "Ref" : "InstanceSecurityGroup" } ], + "KeyName" : { "Ref" : "KeyName" }, + "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, + { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] } + } + }, + + "InstanceSecurityGroup" : { + "Type" : "AWS::EC2::SecurityGroup", + "Properties" : { + "GroupDescription" : "Enable SSH access via port 22", + "SecurityGroupIngress" : [ { + "IpProtocol" : "tcp", + "FromPort" : "22", + "ToPort" : "22", + "CidrIp" : { "Ref" : "SSHLocation"} + } ] + } + } + }, + + "Outputs" : { + "InstanceId" : { + "Description" : "InstanceId of the newly created EC2 instance", + "Value" : { "Ref" : "EC2Instance" } + }, + "AZ" : { + "Description" : "Availability Zone of the newly created EC2 instance", + "Value" : { "Fn::GetAtt" : [ "EC2Instance", "AvailabilityZone" ] } + }, + "PublicDNS" : { + "Description" : "Public DNSName of the newly created EC2 instance", + "Value" : { "Fn::GetAtt" : [ "EC2Instance", "PublicDnsName" ] } + }, + "PublicIP" : { + "Description" : "Public IP address of the newly created EC2 instance", + "Value" : { "Fn::GetAtt" : [ "EC2Instance", "PublicIp" ] } + } + } +} diff --git a/devops-service/lib/stack_template_presets/postgres_cluster.rb b/devops-service/lib/stack_template_presets/postgres_cluster.rb new file mode 100644 index 0000000..28f7255 --- /dev/null +++ b/devops-service/lib/stack_template_presets/postgres_cluster.rb @@ -0,0 +1,4 @@ +module Devops::StackTemplatePresets + class PostgresCluster < Base + end +end \ No newline at end of file diff --git a/devops-service/routes/v2.0.rb b/devops-service/routes/v2.0.rb index 84520ff..aa340b1 100644 --- a/devops-service/routes/v2.0.rb +++ b/devops-service/routes/v2.0.rb @@ -19,6 +19,7 @@ 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_template_presets" require "routes/v2.0/stack" require "routes/v2.0/handlers/provider" @@ -37,6 +38,7 @@ 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_template_preset" require "routes/v2.0/handlers/stack" require "routes/routes_container" diff --git a/devops-service/routes/v2.0/handlers/stack_template_preset.rb b/devops-service/routes/v2.0/handlers/stack_template_preset.rb new file mode 100644 index 0000000..d4a508b --- /dev/null +++ b/devops-service/routes/v2.0/handlers/stack_template_preset.rb @@ -0,0 +1,27 @@ +require 'json' +require 'lib/stack_template_presets/factory' + +module Devops + module Version2_0 + module Handler + class StackTemplatePreset + + def self.get_presets + lambda { + # check_privileges("stack_template_presets", "r") + json Devops::StackTemplatePresetsFactory.list.map(&:to_hash) + } + end + + def self.get_preset + lambda { + # check_privileges("stack_template_presets", "r") + json Devops::StackTemplatePresetsFactory.get(params['id']).to_hash + } + end + + end + end + end +end + diff --git a/devops-service/routes/v2.0/stack_template_presets.rb b/devops-service/routes/v2.0/stack_template_presets.rb new file mode 100644 index 0000000..4bb473d --- /dev/null +++ b/devops-service/routes/v2.0/stack_template_presets.rb @@ -0,0 +1,38 @@ +module Devops + module Version2_0 + module Routes + module KeyRoutes + + def self.registered(app) + # Get list of available stack_template_presets + # + # * *Request* + # - method : GET + # - headers : + # - Accept: application/json + # + # * *Returns* : array of hashes + # [ {id: 'preset id', template_preset_body: 'long body'} ] + # + app.get_with_headers "/stack_template_presets", :headers => [:accept], &Devops::Version2_0::Handler::StackTemplatePreset.get_presets + + + # Get information about stack_template_preset + # + # * *Request* + # - method : GET + # - headers : + # - Accept: application/json + # + # * *Returns* : array of strings + # [ 'postgres_cluster' ] + # + app.get_with_headers "/stack_template_presets/:id", :headers => [:accept], &Devops::Version2_0::Handler::StackTemplatePreset.get_preset + + puts "Stack template presets routes initialized" + end + + end + end + end +end