diff --git a/devops-service/Gemfile b/devops-service/Gemfile index fe1c3b9..96840ba 100644 --- a/devops-service/Gemfile +++ b/devops-service/Gemfile @@ -13,7 +13,6 @@ gem "chef", ">=12" gem "mongo" gem "bson_ext" gem "multi_json", "1.7.8" -# gem "rufus-scheduler", "2.0.24" gem "sidekiq", "3.2.6" gem 'wisper' gem 'rake', '10.2.0' @@ -31,6 +30,7 @@ group :test do gem 'rspec', '~>3.3' gem 'factory_girl', '~>4.5' gem 'activesupport' + gem 'rspec_junit_formatter' end group :devepoment do diff --git a/devops-service/Gemfile.lock b/devops-service/Gemfile.lock index bac5127..b5bf929 100644 --- a/devops-service/Gemfile.lock +++ b/devops-service/Gemfile.lock @@ -350,6 +350,7 @@ DEPENDENCIES rack-accept-media-types rake (= 10.2.0) rspec (~> 3.3) + rspec_junit_formatter sidekiq (= 3.2.6) sinatra (= 1.4.5) sinatra-contrib @@ -357,6 +358,3 @@ DEPENDENCIES test-unit thin (~> 1.5.1) wisper - -BUNDLED WITH - 1.10.5 diff --git a/devops-service/app/api2/handlers/group.rb b/devops-service/app/api2/handlers/group.rb index 82ed2d7..8b44aed 100644 --- a/devops-service/app/api2/handlers/group.rb +++ b/devops-service/app/api2/handlers/group.rb @@ -1,3 +1,4 @@ +require "app/api2/parsers/security_groups" require "providers/provider_factory" require_relative "request_handler" @@ -6,13 +7,15 @@ module Devops module Handler class Group < RequestHandler - # TODO: vpc support for ec2 + set_parser Devops::API2_0::Parser::SecurityGroupsParser + def groups provider groups_with_account(provider, nil) end def groups_with_account provider, account - ::Provider::ProviderFactory.get(provider, account).groups()#params + available_keys = ["vpc-id"] + ::Provider::ProviderFactory.get(provider, account).groups(parser.security_groups.select{|k,v| available_keys.include?(k)}) end end end diff --git a/devops-service/app/api2/handlers/network.rb b/devops-service/app/api2/handlers/network.rb index 25c89ec..24403eb 100644 --- a/devops-service/app/api2/handlers/network.rb +++ b/devops-service/app/api2/handlers/network.rb @@ -1,3 +1,4 @@ +require "app/api2/parsers/network" require "providers/provider_factory" require_relative "request_handler" @@ -6,13 +7,16 @@ module Devops module Handler class Network < RequestHandler + set_parser Devops::API2_0::Parser::NetworkParser + def networks provider networks_with_account provider, nil end def networks_with_account provider, account p = ::Provider::ProviderFactory.get(provider, account) - p.networks_detail + available_keys = ["vpc-id"] + p.networks_detail(parser.networks.select{|k,v| available_keys.include?(k)}) end end end diff --git a/devops-service/app/api2/handlers/provider.rb b/devops-service/app/api2/handlers/provider.rb index a054f2c..8e5445d 100644 --- a/devops-service/app/api2/handlers/provider.rb +++ b/devops-service/app/api2/handlers/provider.rb @@ -33,12 +33,17 @@ module Devops end def delete_account name, provider - account = Devops::Db.connector.provider_accounts_show(name) + account = Devops::Db.connector.provider_account(provider, name) Devops::Db.connector.provider_accounts_delete(name) ::Provider::ProviderFactory.delete_account(provider, account) account.to_hash end + def account_vpcs provider, name + Devops::Db.connector.provider_account(provider, name) + ::Provider::ProviderFactory.get(provider, name).describe_vpcs + end + end end end diff --git a/devops-service/app/api2/parsers/network.rb b/devops-service/app/api2/parsers/network.rb new file mode 100644 index 0000000..e808cc3 --- /dev/null +++ b/devops-service/app/api2/parsers/network.rb @@ -0,0 +1,15 @@ +require_relative "request_parser" + +module Devops + module API2_0 + module Parser + class NetworkParser < RequestParser + + def networks + @params + end + end + end + end +end + diff --git a/devops-service/app/api2/parsers/security_groups.rb b/devops-service/app/api2/parsers/security_groups.rb new file mode 100644 index 0000000..80cb019 --- /dev/null +++ b/devops-service/app/api2/parsers/security_groups.rb @@ -0,0 +1,15 @@ +require_relative "request_parser" + +module Devops + module API2_0 + module Parser + class SecurityGroupsParser < RequestParser + + def security_groups + @params + end + end + end + end +end + diff --git a/devops-service/app/api2/routes/group.rb b/devops-service/app/api2/routes/group.rb index 989c4fb..182d82f 100644 --- a/devops-service/app/api2/routes/group.rb +++ b/devops-service/app/api2/routes/group.rb @@ -13,6 +13,9 @@ module Devops # - headers : # - Accept: application/json # + # * Params: + # vpc-id - string + # # * *Returns* : # - ec2: # { @@ -43,7 +46,6 @@ module Devops # ] # } # } - # TODO: vpc support for ec2 app.get_with_headers "/groups/:provider", :headers => [:accept] do |provider| check_privileges("group", "r") check_provider(provider) diff --git a/devops-service/app/api2/routes/network.rb b/devops-service/app/api2/routes/network.rb index 5da6724..f984438 100644 --- a/devops-service/app/api2/routes/network.rb +++ b/devops-service/app/api2/routes/network.rb @@ -13,6 +13,9 @@ module Devops # - headers : # - Accept: application/json # + # * Params: + # vpc-id - string + # # * *Returns* : array of strings # - ec2: # [ diff --git a/devops-service/app/api2/routes/project.rb b/devops-service/app/api2/routes/project.rb index 7b66b61..62e4b12 100644 --- a/devops-service/app/api2/routes/project.rb +++ b/devops-service/app/api2/routes/project.rb @@ -175,7 +175,7 @@ module Devops # Deletes project servers # # * *Request* - # - method : PATCH + # - method : DELETE # - headers : # - Accept: application/json # - Content-Type: application/json diff --git a/devops-service/app/api2/routes/provider.rb b/devops-service/app/api2/routes/provider.rb index 49a797e..dd51af9 100644 --- a/devops-service/app/api2/routes/provider.rb +++ b/devops-service/app/api2/routes/provider.rb @@ -115,7 +115,23 @@ module Devops app.delete_with_headers "/provider/:provider/account/:account_name", :headers => [:accept, :content_type] do |provider, account_name| check_privileges("provider", "w") check_provider(provider) - create_response("Deleted", {:account => Devops::API2_0::Handler::Provider.new(request).delete_account(provider)}) + create_response("Deleted", {:account => Devops::API2_0::Handler::Provider.new(request).delete_account(account_name, provider)}) + end + + # Describe vpc for account with name :account_name for provider ec2 + # + # * *Request* + # - method : GET + # - headers : + # - Accept: application/json + # - Content-Type: application/json + # + # * *Returns* : 200 + app.get_with_headers "/provider/ec2/account/:account_name/vpcs", :headers => [:accept, :content_type] do |account_name| + provider = "ec2" + check_privileges("provider", "r") + check_provider(provider) + json Devops::API2_0::Handler::Provider.new(request).account_vpcs(provider, account_name) end puts "Provider routes initialized" diff --git a/devops-service/db/mongo/connectors/provider_accounts.rb b/devops-service/db/mongo/connectors/provider_accounts.rb index 3627562..4bd235a 100644 --- a/devops-service/db/mongo/connectors/provider_accounts.rb +++ b/devops-service/db/mongo/connectors/provider_accounts.rb @@ -13,6 +13,13 @@ module Connectors collection.find({provider: provider}).to_a.map{|bson| c.build_from_bson(bson)} end + def provider_account provider, account + c = Provider::ProviderFactory.get_account_class(provider) + bson = collection.find({provider: provider, _id: account}).to_a.first + raise RecordNotFound.new("'Account #{account}' for provider '#{provider}' not found") unless bson + c.build_from_bson(bson) + end + def collection_name 'provider_accounts' end diff --git a/devops-service/db/mongo/models/deploy_env/cloud_deploy_env.rb b/devops-service/db/mongo/models/deploy_env/cloud_deploy_env.rb index 628ca17..a19abcc 100644 --- a/devops-service/db/mongo/models/deploy_env/cloud_deploy_env.rb +++ b/devops-service/db/mongo/models/deploy_env/cloud_deploy_env.rb @@ -11,28 +11,29 @@ module Devops module Model class CloudDeployEnv < DeployEnvBase - attr_accessor :flavor, :image, :subnets, :groups, :stack_template +# attr_accessor :flavor, :image, :subnets, :groups, :stack_template set_validators ::Validators::DeployEnv::Flavor, ::Validators::DeployEnv::Image, ::Validators::DeployEnv::Groups, ::Validators::DeployEnv::StackTemplate # set_validators ::Validators::DeployEnv::CloudParameters - set_field_validators :flavor, ::Validators::FieldValidator::Nil, + set_field_validators :flavor, [::Validators::FieldValidator::Nil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::Flavor - set_field_validators :image, ::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::Flavor], order: 2 + set_field_validators :image, [::Validators::FieldValidator::Nil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::Image - set_field_validators :subnets, ::Validators::FieldValidator::Nil, - ::Validators::FieldValidator::FieldType::Array + ::Validators::FieldValidator::Image], order: 2 + set_field_validators :subnets, [::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::FieldType::Array], order: 4 # ::Validators::FieldValidator::Subnets.new - set_field_validators :groups, ::Validators::FieldValidator::Nil, - ::Validators::FieldValidator::FieldType::Array + set_field_validators :groups, [::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::FieldType::Array], order: 4 # ::Validators::FieldValidator::Groups.new - set_field_validators :stack_template, ::Validators::FieldValidator::Nil, + set_field_validators :stack_template, [::Validators::FieldValidator::Nil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty + ::Validators::FieldValidator::NotEmpty], order: 2 +# ::Validators::FieldValidator::StackTemplate.new def initialize d={} super(d) diff --git a/devops-service/db/mongo/models/deploy_env/deploy_env_base.rb b/devops-service/db/mongo/models/deploy_env/deploy_env_base.rb index 0f2bfec..d95d71c 100644 --- a/devops-service/db/mongo/models/deploy_env/deploy_env_base.rb +++ b/devops-service/db/mongo/models/deploy_env/deploy_env_base.rb @@ -8,27 +8,27 @@ module Devops include ModelWithProvider - attr_accessor :identifier, :run_list, :expires, :users +# attr_accessor :identifier, :run_list, :expires, :users set_validators ::Validators::DeployEnv::RunList, ::Validators::DeployEnv::Expiration, ::Validators::DeployEnv::Users - set_field_validators :identifier, ::Validators::FieldValidator::NotNil, + set_field_validators :identifier, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty, - ::Validators::FieldValidator::Name + ::Validators::FieldValidator::Name] - set_field_validators :run_list, ::Validators::FieldValidator::NotNil, + set_field_validators :run_list, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::Array, - ::Validators::FieldValidator::RunList + ::Validators::FieldValidator::RunList] - set_field_validators :users, ::Validators::FieldValidator::NotNil, - ::Validators::FieldValidator::FieldType::Array + set_field_validators :users, [::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::Array] - set_field_validators :expires, ::Validators::FieldValidator::Nil, + set_field_validators :expires, [::Validators::FieldValidator::Nil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::Expires + ::Validators::FieldValidator::Expires] def initialize d={} self.identifier = d["identifier"] diff --git a/devops-service/db/mongo/models/deploy_env/deploy_env_ec2.rb b/devops-service/db/mongo/models/deploy_env/deploy_env_ec2.rb index b6285bc..49cdfad 100644 --- a/devops-service/db/mongo/models/deploy_env/deploy_env_ec2.rb +++ b/devops-service/db/mongo/models/deploy_env/deploy_env_ec2.rb @@ -4,6 +4,11 @@ module Devops module Model class DeployEnvEc2 < CloudDeployEnv +# attr_accessor :vpc_id + + set_field_validators :vpc_id, [::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::Vpc], order: 3 =begin @Deprecated types :identifier => {:type => String, :empty => false}, @@ -34,6 +39,11 @@ module Devops if self.subnets.size > 1 self.subnets = [ self.subnets[0] ] end + self.vpc_id = d["vpc_id"] + end + + def to_hash + super().merge({"vpc_id" => self.vpc_id}) end def self.create hash diff --git a/devops-service/db/mongo/models/image.rb b/devops-service/db/mongo/models/image.rb index d5398e7..dace22e 100644 --- a/devops-service/db/mongo/models/image.rb +++ b/devops-service/db/mongo/models/image.rb @@ -8,7 +8,7 @@ module Devops class Image < MongoModel include ModelWithProvider - attr_accessor :id, :remote_user, :name, :bootstrap_template +# attr_accessor :id, :remote_user, :name, :bootstrap_template =begin types :id => {:type => String, :empty => false}, :provider => {:type => String, :empty => false}, @@ -20,27 +20,27 @@ module Devops # set_validators ::Validators::Image::ImageInFilter, # ::Validators::Image::BootstrapTemplate - set_field_validators :id, ::Validators::FieldValidator::NotNil, + set_field_validators :id, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty, ::Validators::FieldValidator::ImageName, - ::Validators::Image::ImageInFilter + ::Validators::Image::ImageInFilter] - set_field_validators :remote_user, ::Validators::FieldValidator::NotNil, + set_field_validators :remote_user, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty, - ::Validators::FieldValidator::ImageName + ::Validators::FieldValidator::ImageName] - set_field_validators :name, ::Validators::FieldValidator::NotNil, + set_field_validators :name, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty, - ::Validators::FieldValidator::ImageName + ::Validators::FieldValidator::ImageName] - set_field_validators :bootstrap_template, ::Validators::FieldValidator::Nil, + set_field_validators :bootstrap_template, [::Validators::FieldValidator::Nil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty, ::Validators::FieldValidator::Name, - ::Validators::Image::BootstrapTemplate + ::Validators::Image::BootstrapTemplate] def validate! validate_id! diff --git a/devops-service/db/mongo/models/model_with_provider.rb b/devops-service/db/mongo/models/model_with_provider.rb index 850b7ee..b7a5d36 100644 --- a/devops-service/db/mongo/models/model_with_provider.rb +++ b/devops-service/db/mongo/models/model_with_provider.rb @@ -4,14 +4,19 @@ module Devops module Model module ModelWithProvider - attr_accessor :provider, :provider_account +# attr_accessor :provider, :provider_account def ModelWithProvider.included(mod) - mod.set_field_validators :provider, ::Validators::FieldValidator::NotNil, + mod.set_field_validators :provider, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty, - ::Validators::FieldValidator::Provider + ::Validators::FieldValidator::Provider] + + mod.set_field_validators :provider_account, [::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::NotEmpty, + ::Validators::FieldValidator::ProviderAccount], order: 1 end def provider_instance diff --git a/devops-service/db/mongo/models/mongo_model.rb b/devops-service/db/mongo/models/mongo_model.rb index 690576c..7525187 100644 --- a/devops-service/db/mongo/models/mongo_model.rb +++ b/devops-service/db/mongo/models/mongo_model.rb @@ -69,15 +69,20 @@ module Devops def validate_fields! result = [] - self.class.field_validators.each do |field, validation_method| - begin - self.send(validation_method) - rescue InvalidRecord => e - result << {key: field, message: e.message} + orders = self.class.field_validators.keys.sort + orders.each do |order| + self.class.field_validators[order].each do |elem| + field = elem[:field] + validation_method = elem[:method] + begin + self.send(validation_method) + rescue InvalidRecord => e + result << {key: field, message: e.message} + end + end + unless result.empty? + raise InvalidRecord.new(error_data: result) end - end - unless result.empty? - raise InvalidRecord.new(error_data: result) end true end @@ -150,6 +155,12 @@ module Devops class << self attr_accessor :validators + + # hash: + # key - (integer) validators order + # value - (hash) validator params: + # field: (string) field name + # method: (string) field validator method attr_accessor :field_validators def inherited(subclass) @@ -168,14 +179,29 @@ module Devops # validate field value # if method validate! returns false, then stop validation without error - def set_field_validators field, *validators + # + # field - (string) field name to validate + # validators - (array) validators list + # options - (hash) options for validator + # order: integer - run validator in order with index order: + def set_field_validators field, validators, options={} + attr_accessor field method_name = "validate_" + field.to_s + "!" define_method(method_name) do validators.each do |validator| - break unless validator.new(self, send(field)).validate! + break unless validator.new(self, field).validate! end end - self.field_validators[field] = method_name + order = options[:order] || 0 + obj = { + field: field, + method: method_name + } + unless self.field_validators[order] + self.field_validators[order] = [obj] + else + self.field_validators[order] << obj + end end # private class methods diff --git a/devops-service/db/mongo/models/project.rb b/devops-service/db/mongo/models/project.rb index 9f0f568..e34a779 100644 --- a/devops-service/db/mongo/models/project.rb +++ b/devops-service/db/mongo/models/project.rb @@ -93,11 +93,16 @@ module Devops def check_authorization user_id, env e = self.deploy_env(env) return true if user_id == User::ROOT_USER_NAME + return true if is_sandbox? return e.users.include? user_id rescue RecordNotFound => e return false end + def is_sandbox? + id.start_with?('sandbox-') + end + =begin def validate! super diff --git a/devops-service/db/mongo/models/provider_accounts/ec2_provider_account.rb b/devops-service/db/mongo/models/provider_accounts/ec2_provider_account.rb index 7453835..d839e5e 100644 --- a/devops-service/db/mongo/models/provider_accounts/ec2_provider_account.rb +++ b/devops-service/db/mongo/models/provider_accounts/ec2_provider_account.rb @@ -6,16 +6,16 @@ module Devops attr_accessor :availability_zone - set_field_validators :access_key_id, ::Validators::FieldValidator::NotNil, + set_field_validators :access_key_id, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty + ::Validators::FieldValidator::NotEmpty] - set_field_validators :secret_access_key, ::Validators::FieldValidator::NotNil, + set_field_validators :secret_access_key, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty + ::Validators::FieldValidator::NotEmpty] - set_field_validators :use_iam_profile, ::Validators::FieldValidator::Nil, - ::Validators::FieldValidator::FieldType::Boolean + set_field_validators :use_iam_profile, [::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::FieldType::Boolean] def initialize a={} super(a) self.provider = Provider::Ec2::PROVIDER diff --git a/devops-service/db/mongo/models/provider_accounts/provider_account.rb b/devops-service/db/mongo/models/provider_accounts/provider_account.rb index 3a6fb59..d3c9c42 100644 --- a/devops-service/db/mongo/models/provider_accounts/provider_account.rb +++ b/devops-service/db/mongo/models/provider_accounts/provider_account.rb @@ -7,22 +7,22 @@ module Devops include ModelWithProvider - attr_accessor :account_name, :description, :ssh_key +# attr_accessor :account_name, :description, :ssh_key - set_field_validators :account_name, ::Validators::FieldValidator::NotNil, + set_field_validators :account_name, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty, - ::Validators::FieldValidator::Name + ::Validators::FieldValidator::Name] - set_field_validators :description, ::Validators::FieldValidator::Nil, + set_field_validators :description, [::Validators::FieldValidator::Nil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty, - ::Validators::FieldValidator::Description + ::Validators::FieldValidator::Description] - set_field_validators :ssh_key, ::Validators::FieldValidator::NotNil, + set_field_validators :ssh_key, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty, - ::Validators::FieldValidator::SshKey + ::Validators::FieldValidator::SshKey] ACCOUNT_FIELDS = { account_name: "Account name (id)", diff --git a/devops-service/db/mongo/models/stack/stack_base.rb b/devops-service/db/mongo/models/stack/stack_base.rb index a6bea8c..cf118e5 100644 --- a/devops-service/db/mongo/models/stack/stack_base.rb +++ b/devops-service/db/mongo/models/stack/stack_base.rb @@ -19,37 +19,37 @@ module Devops run_list: {type: Array, value_type: String, empty: true, nil: true} # details: {type: Hash, nil: true} # Hash type isn't supported yet - set_field_validators :id, ::Validators::FieldValidator::NotNil, + set_field_validators :id, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty + ::Validators::FieldValidator::NotEmpty] - set_field_validators :provider, ::Validators::FieldValidator::NotNil, + set_field_validators :provider, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty + ::Validators::FieldValidator::NotEmpty] - set_field_validators :project, ::Validators::FieldValidator::NotNil, + set_field_validators :project, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty + ::Validators::FieldValidator::NotEmpty] - set_field_validators :deploy_env, ::Validators::FieldValidator::NotNil, + set_field_validators :deploy_env, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty + ::Validators::FieldValidator::NotEmpty] - set_field_validators :stack_template, ::Validators::FieldValidator::NotNil, + set_field_validators :stack_template, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty + ::Validators::FieldValidator::NotEmpty] - set_field_validators :name, ::Validators::FieldValidator::Nil, + set_field_validators :name, [::Validators::FieldValidator::Nil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty + ::Validators::FieldValidator::NotEmpty] - set_field_validators :owner, ::Validators::FieldValidator::NotNil, + set_field_validators :owner, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty + ::Validators::FieldValidator::NotEmpty] - set_field_validators :run_list, ::Validators::FieldValidator::NotNil, + set_field_validators :run_list, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::Array, - ::Validators::FieldValidator::RunList + ::Validators::FieldValidator::RunList] def initialize attrs={} # self.provider = self.class.provider diff --git a/devops-service/db/mongo/models/stack_template/stack_template_base.rb b/devops-service/db/mongo/models/stack_template/stack_template_base.rb index 6e43166..2bdfb1e 100644 --- a/devops-service/db/mongo/models/stack_template/stack_template_base.rb +++ b/devops-service/db/mongo/models/stack_template/stack_template_base.rb @@ -16,22 +16,22 @@ module Devops template_body: {type: String, empty: false}, owner: {type: String, empty: false} - set_field_validators :id, ::Validators::FieldValidator::NotNil, + set_field_validators :id, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty, + ::Validators::FieldValidator::NotEmpty,] ::Validators::FieldValidator::Name - set_field_validators :provider, ::Validators::FieldValidator::NotNil, + set_field_validators :provider, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty + ::Validators::FieldValidator::NotEmpty] - set_field_validators :template_body, ::Validators::FieldValidator::NotNil, + set_field_validators :template_body, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty + ::Validators::FieldValidator::NotEmpty] - set_field_validators :owner, ::Validators::FieldValidator::NotNil, + set_field_validators :owner, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::NotEmpty + ::Validators::FieldValidator::NotEmpty] set_validators ::Validators::StackTemplate::TemplateContent diff --git a/devops-service/db/mongo/models/user.rb b/devops-service/db/mongo/models/user.rb index 89d21fa..c24247e 100644 --- a/devops-service/db/mongo/models/user.rb +++ b/devops-service/db/mongo/models/user.rb @@ -17,15 +17,15 @@ module Devops attr_accessor :id, :password, :privileges, :email - set_field_validators :id, ::Validators::FieldValidator::NotNil, + set_field_validators :id, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, - ::Validators::FieldValidator::Name - set_field_validators :password, ::Validators::FieldValidator::NotNil, - ::Validators::FieldValidator::FieldType::String - set_field_validators :email, ::Validators::FieldValidator::NotNil, - ::Validators::FieldValidator::FieldType::String - set_field_validators :privileges, ::Validators::FieldValidator::NotNil, - ::Validators::FieldValidator::FieldType::Hash + ::Validators::FieldValidator::Name] + set_field_validators :password, [::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String] + set_field_validators :email, [::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String] + set_field_validators :privileges, [::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::Hash] def initialize p={} self.id = p['username'] self.email = p['email'] diff --git a/devops-service/db/mongo/mongo_connector.rb b/devops-service/db/mongo/mongo_connector.rb index bda584e..baa47ff 100644 --- a/devops-service/db/mongo/mongo_connector.rb +++ b/devops-service/db/mongo/mongo_connector.rb @@ -33,7 +33,7 @@ class MongoConnector [:keys, :key, :key_insert, :key_delete] => :keys_connector, [:save_report, :report, :reports, :set_report_status, :set_report_server_data, :add_report_subreports] => :reports_connector, [:insert_statistic, :search_statistic] => :statistics_connector, - [:provider_accounts, :provider_accounts_insert, :provider_accounts_delete, :provider_accounts_show] => :provider_accounts_connector + [:provider_accounts, :provider_accounts_insert, :provider_accounts_delete, :provider_account] => :provider_accounts_connector ) def initialize(db, host, port=27017, user=nil, password=nil) diff --git a/devops-service/db/validators/field_validators/base.rb b/devops-service/db/validators/field_validators/base.rb index 8c60d57..c76395b 100644 --- a/devops-service/db/validators/field_validators/base.rb +++ b/devops-service/db/validators/field_validators/base.rb @@ -2,9 +2,10 @@ module Validators module FieldValidator class Base - def initialize model, value + def initialize model, field @model = model - @value = value + @field = field + @value = model.send(field) end def validate! diff --git a/devops-service/db/validators/field_validators/name.rb b/devops-service/db/validators/field_validators/name.rb index 4603934..3da7928 100644 --- a/devops-service/db/validators/field_validators/name.rb +++ b/devops-service/db/validators/field_validators/name.rb @@ -4,14 +4,14 @@ module Validators class Name < Base MAX_NAME_LEN = 200 - NAME_REGEX = /\A\w{1,#{MAX_NAME_LEN}}\z/ + NAME_REGEX = /\A[\w\-]{1,#{MAX_NAME_LEN}}\z/ def valid? !NAME_REGEX.match(@value).nil? end def message - "Invalid value '#{@value}': it should contains symbols 'a-zA-Z0-9_' and length should be more then 1 and less or equals then #{MAX_NAME_LEN} symbols" + "Invalid value '#{@value}': it should contains symbols 'a-zA-Z0-9_-' and length should be more then 1 and less or equals then #{MAX_NAME_LEN} symbols" end end end diff --git a/devops-service/db/validators/field_validators/provider_account.rb b/devops-service/db/validators/field_validators/provider_account.rb new file mode 100644 index 0000000..3d56074 --- /dev/null +++ b/devops-service/db/validators/field_validators/provider_account.rb @@ -0,0 +1,17 @@ +require_relative "base" + +module Validators + module FieldValidator + class ProviderAccount < Base + + def valid? + accounts = AccountsFactory.accounts(@model.provider) + accounts.map{|a| a.account_name}.include?(@value) + end + + def message + "Account '#{@value}' for provider '#{@model.provider}' does not exist" + end + end + end +end diff --git a/devops-service/db/validators/field_validators/vpc.rb b/devops-service/db/validators/field_validators/vpc.rb new file mode 100644 index 0000000..f932dc6 --- /dev/null +++ b/devops-service/db/validators/field_validators/vpc.rb @@ -0,0 +1,21 @@ +require_relative "base" + +module Validators + module FieldValidator + class Vpc < Base + + def valid? + provider = ::Provider::ProviderFactory.get(@model.provider, @model.provider_account) + vpcs = provider.describe_vpcs + vpcs.keys.include?(@value) + rescue + raise "Invalid provider account '#{@model.provider_account}'" + end + + def message + "Invalid vpc '#{@value}'." + end + end + end +end + diff --git a/devops-service/exceptions/invalid_record.rb b/devops-service/exceptions/invalid_record.rb index 48d3750..89fd18d 100644 --- a/devops-service/exceptions/invalid_record.rb +++ b/devops-service/exceptions/invalid_record.rb @@ -1,6 +1,10 @@ require_relative "devops_error" class InvalidRecord < ::Devops::Exception::DevopsError + # message could be a String or a hash like + # { + # error_data: [{:key=>:provider, :message=>"Value can not be undefined"}] + # } def initialize msg if msg.is_a?(String) super(msg) @@ -9,6 +13,17 @@ class InvalidRecord < ::Devops::Exception::DevopsError end end + def message + if @object + messages = @object[:error_data].map do |error_item| + "#{error_item[:key]}: #{error_item[:message]}" + end + "Following errors occured: \n#{messages.join('\n')}" + else + super + end + end + def http_status 400 end diff --git a/devops-service/providers/accounts_factory.rb b/devops-service/providers/accounts_factory.rb index 7f212e9..07906e1 100644 --- a/devops-service/providers/accounts_factory.rb +++ b/devops-service/providers/accounts_factory.rb @@ -1,6 +1,14 @@ module Provider class AccountsFactory + class << self + + def accounts provider_name + Devops::Db.connector.provider_accounts(provider_name) + end + + end + def init config end @@ -22,7 +30,7 @@ module Provider end def accounts - Devops::Db.connector.provider_accounts(provider_name) + AccountsFactory.accounts(provider_name) end def create_account hash diff --git a/devops-service/providers/base_provider.rb b/devops-service/providers/base_provider.rb index 5ba85a4..e399e4f 100644 --- a/devops-service/providers/base_provider.rb +++ b/devops-service/providers/base_provider.rb @@ -14,6 +14,18 @@ module Provider "stack_#{self.ssh_key}-#{s.project}-#{s.deploy_env}-#{Time.now.to_i}" end + def networks_detail filters={} + networks(filters) + end + + def networks filters={} + [] + end + + def groups filters={} + {} + end + protected def connection_compute options Fog::Compute.new( options ) diff --git a/devops-service/providers/ec2.rb b/devops-service/providers/ec2.rb index b001baa..a51b423 100644 --- a/devops-service/providers/ec2.rb +++ b/devops-service/providers/ec2.rb @@ -55,14 +55,8 @@ module Provider end end - def groups filters=nil - buf = {} - buf = filters.select{|k,v| ["vpc-id"].include?(k)} unless filters.nil? - g = if buf.empty? - self.compute.describe_security_groups - else - self.compute.describe_security_groups(buf) - end + def groups filters={} + g = self.compute.describe_security_groups(filters) convert_groups(g.body["securityGroupInfo"]) end @@ -76,12 +70,8 @@ module Provider end end - def networks_detail - self.networks - end - - def networks - self.compute.describe_subnets.body["subnetSet"].select{|n| n["state"] == "available"}.map do |n| + def networks filters={} + self.compute.describe_subnets(filters).body["subnetSet"].select{|n| n["state"] == "available"}.map do |n| { "cidr" => n["cidrBlock"], "vpcId" => n["vpcId"], @@ -219,7 +209,7 @@ module Provider end def cloud_formation - @cloud_formation ||= Fog::AWS::CloudFormation.new(connection_options) + @cloud_formation ||= Fog::AWS::CloudFormation.new(connection_options) end def create_stack(stack, out) @@ -325,6 +315,10 @@ module Provider def create_default_stack_name s "stack-#{self.ssh_key}-#{s.project}-#{s.deploy_env}-#{Time.now.to_i}".gsub('_', '-') end + + def describe_vpcs + self.compute.describe_vpcs.body["vpcSet"].select{|v| v["state"] == "available"}.map{|v| {"vpc_id" => v["vpcId"], "cidr" => v["cidrBlock"] } } + end private def convert_groups list diff --git a/devops-service/providers/openstack.rb b/devops-service/providers/openstack.rb index 6e8249e..d4807e9 100644 --- a/devops-service/providers/openstack.rb +++ b/devops-service/providers/openstack.rb @@ -30,7 +30,7 @@ module Provider PROVIDER end - def groups filter=nil + def groups filters={} convert_groups(compute.list_security_groups.body["security_groups"]) end @@ -55,8 +55,8 @@ module Provider end end - def networks_detail - net = self.network + def networks_detail filters={} + net = self.network(filters) subnets = net.list_subnets.body["subnets"].select{|s| net.current_tenant["id"] == s["tenant_id"]} net.list_networks.body["networks"].select{|n| n["router:external"] == false and n["status"] == "ACTIVE" and net.current_tenant["id"] == n["tenant_id"]}.map{|n| sn = subnets.detect{|s| n["subnets"][0] == s["id"]} @@ -68,7 +68,7 @@ module Provider } end - def networks + def networks filters={} net = self.network net.list_networks.body["networks"].select{|n| n["router:external"] == false and n["status"] == "ACTIVE" and net.current_tenant["id"] == n["tenant_id"]}.map{|n| { diff --git a/devops-service/providers/static.rb b/devops-service/providers/static.rb index 4f1d788..e3fcb94 100644 --- a/devops-service/providers/static.rb +++ b/devops-service/providers/static.rb @@ -23,22 +23,10 @@ module Provider [] end - def groups filter=nil - {} - end - def images filters [] end - def networks - [] - end - - def networks_detail - self.networks - end - def servers @@mongo.servers_find({:provider => PROVIDER}).map{|s| s.to_hash} end diff --git a/devops-service/spec/models/image_spec.rb b/devops-service/spec/models/image_spec.rb index be7da26..769e04a 100644 --- a/devops-service/spec/models/image_spec.rb +++ b/devops-service/spec/models/image_spec.rb @@ -16,7 +16,7 @@ RSpec.describe Devops::Model::Image, type: :model do describe 'validation' do include_examples 'field type validation', :id, :not_nil, :non_empty_string, :field_validator - include_examples 'field type validation', :remote_user, :not_nil, :non_empty_string, :only_word_symbols, :field_validator + include_examples 'field type validation', :remote_user, :not_nil, :non_empty_string, :field_validator include_examples 'field type validation', :name, :not_nil, :non_empty_string, :field_validator include_examples 'field type validation', :bootstrap_template, :maybe_nil, :non_empty_string, :only_word_symbols, :field_validator @@ -36,6 +36,12 @@ RSpec.describe Devops::Model::Image, type: :model do it 'bootstrap_template should be included in available bootstrap templates' do expect(build(:image, bootstrap_template: 'wrong')).not_to be_valid end + + it 'remote_user should contain only a-zA-Z0-9_-.' do + expect(build(:image, remote_user: 'aA0-.')).to be_valid + expect(build(:image, remote_user: 'name/')).not_to be_valid + expect(build(:image, remote_user: 'name!')).not_to be_valid + end end it '#to_hash_without_id returns provider, name, remote_user and bootstrap_template' do diff --git a/devops-service/spec/models/report_spec.rb b/devops-service/spec/models/report_spec.rb index ab06af3..5d03e5b 100644 --- a/devops-service/spec/models/report_spec.rb +++ b/devops-service/spec/models/report_spec.rb @@ -4,20 +4,16 @@ RSpec.describe Devops::Model::Report, type: :model do let(:report) { build(:report) } describe '#initialize' do + let(:given_moment) { Time.new(2007,11,1,15,25,0, "+01:00") } + it 'converts created_at to localtime' do - now = Time.now.utc - expect(now.zone).to eq 'UTC' - expect( - build(:report, created_at: now).created_at.zone - ).not_to eq 'UTC' + converted = build(:report, created_at: given_moment).created_at + expect(converted).to eq given_moment.localtime end it 'converts updated_at to localtime' do - now = Time.now.utc - expect(now.zone).to eq 'UTC' - expect( - build(:report, updated_at: now).updated_at.zone - ).not_to eq 'UTC' + converted = build(:report, updated_at: given_moment).updated_at + expect(converted).to eq given_moment.localtime end end diff --git a/devops-service/workers/stack_bootstrap_worker.rb b/devops-service/workers/stack_bootstrap_worker.rb index c7298b0..6ad25d7 100644 --- a/devops-service/workers/stack_bootstrap_worker.rb +++ b/devops-service/workers/stack_bootstrap_worker.rb @@ -184,6 +184,7 @@ class StackBootstrapWorker < Worker stack_servers_with_priority = {} stack_servers_info.each do |priority, info_array| stack_servers_with_priority[priority] = info_array.map do |extended_info| + @out.puts "Instance '#{extended_info["id"]}' has been launched with stack." server_attrs = { 'provider' => provider.name, 'project' => project.id,