diff --git a/devops-service/db/mongo/models/image.rb b/devops-service/db/mongo/models/image.rb index dace22e..0263562 100644 --- a/devops-service/db/mongo/models/image.rb +++ b/devops-service/db/mongo/models/image.rb @@ -23,13 +23,13 @@ module Devops set_field_validators :id, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty, - ::Validators::FieldValidator::ImageName, + ::Validators::FieldValidator::ImageId, ::Validators::Image::ImageInFilter] set_field_validators :remote_user, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty, - ::Validators::FieldValidator::ImageName] + ::Validators::FieldValidator::ImageUsername] set_field_validators :name, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, diff --git a/devops-service/db/validators/field_validators/image_id.rb b/devops-service/db/validators/field_validators/image_id.rb new file mode 100644 index 0000000..926a2f6 --- /dev/null +++ b/devops-service/db/validators/field_validators/image_id.rb @@ -0,0 +1,18 @@ +require_relative "base" +module Validators + module FieldValidator + class ImageId < Base + + MAX_LEN = 100 + NAME_REGEX = /\A[\w\-\.]{1,#{MAX_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_LEN}" + end + end + end +end diff --git a/devops-service/db/validators/field_validators/image_name.rb b/devops-service/db/validators/field_validators/image_name.rb index e886a53..c108246 100644 --- a/devops-service/db/validators/field_validators/image_name.rb +++ b/devops-service/db/validators/field_validators/image_name.rb @@ -3,15 +3,14 @@ module Validators module FieldValidator class ImageName < Base - MAX_NAME_LEN = 100 - NAME_REGEX = /\A[\w\-\.]{1,#{MAX_NAME_LEN}}\z/ + MAX_LEN = 100 def valid? - !NAME_REGEX.match(@value).nil? + @value.length <= MAX_LEN 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}" + "Invalid value '#{@value}': it should contains symbols 'a-zA-Z0-9_-.' and length should be more then 1 and less or equals then #{MAX_LEN}" end end end diff --git a/devops-service/db/validators/field_validators/image_username.rb b/devops-service/db/validators/field_validators/image_username.rb new file mode 100644 index 0000000..334011d --- /dev/null +++ b/devops-service/db/validators/field_validators/image_username.rb @@ -0,0 +1,18 @@ +require_relative "base" +module Validators + module FieldValidator + class ImageUsername < Base + + MAX_NAME_LEN = 100 + 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}" + end + end + end +end diff --git a/devops-service/lib/executors/server_executor.rb b/devops-service/lib/executors/server_executor.rb index 7ff7fdc..0518211 100644 --- a/devops-service/lib/executors/server_executor.rb +++ b/devops-service/lib/executors/server_executor.rb @@ -2,6 +2,7 @@ require "lib/knife/knife_factory" require "workers/worker" require "workers/delete_server_worker" require "hooks" +require 'net/ssh' module Devops module Executor @@ -312,15 +313,26 @@ module Devops res = delete_from_chef_server(@server.chef_node_name) begin new_name = "/etc/chef.backup_#{Time.now.strftime("%d-%m-%Y_%H.%M.%S")}" -# r = `ssh -i #{cert_path} -q #{@server.remote_user}@#{@server.private_ip} rm -Rf /etc/chef` - cmd = "ssh -i #{cert_path} -q #{@server.remote_user}@#{@server.private_ip} \"/bin/sh -c 'if [[ -d /etc/chef ]]; then mv /etc/chef #{new_name}; else echo not found; fi'\"" - DevopsLogger.logger.info("Trying to run command '#{cmd}'") - r = `#{cmd}`.strip - if r == 'not found' - res[:server] = "Directory '/etc/chef' does not exists" - else - raise(r) unless $?.success? - res[:server] = "'/etc/chef' renamed to '#{new_name}'" + cmd = (@server.remote_user == 'root' ? "" : "sudo ") + cmd = cmd + "/bin/sh -c 'if [[ -d /etc/chef ]]; then mv /etc/chef #{new_name} && echo ok; else echo not found; fi'" + DevopsLogger.logger.info("SSH: trying to run command '#{cmd}'") + Net::SSH.start(@server.private_ip, @server.remote_user, :keys => [cert_path]) do |session| + session.open_channel do |channel| + channel.request_pty(:modes => { Net::SSH::Connection::Term::ECHO => 0 }) do |c, success| + raise "could not request pty" unless success + channel.exec cmd + channel.on_data do |c_, data| + if data == 'not found' + res[:server] = "Directory '/etc/chef' does not exists" + elsif data == 'ok' + res[:server] = "'/etc/chef' renamed to '#{new_name}'" + else + DevopsLogger.logger.error "Unexpected error: " + data + raise(data) + end + end + end + end end rescue => e DevopsLogger.logger.error "Unbootstrap error: " + e.message diff --git a/devops-service/providers/ec2.rb b/devops-service/providers/ec2.rb index b62a32f..174e7e8 100644 --- a/devops-service/providers/ec2.rb +++ b/devops-service/providers/ec2.rb @@ -261,8 +261,9 @@ module Provider end def validate_stack_template template - r = cloud_formation.validate_template({'TemplateBody' => template}) - pp r.body + #r = cloud_formation.validate_template({'TemplateBody' => template}) + #pp r.body + true end def delete_stack(stack) diff --git a/devops-service/spec/models/image_spec.rb b/devops-service/spec/models/image_spec.rb index 769e04a..a90912d 100644 --- a/devops-service/spec/models/image_spec.rb +++ b/devops-service/spec/models/image_spec.rb @@ -2,12 +2,13 @@ require 'db/mongo/models/image' RSpec.describe Devops::Model::Image, type: :model do let(:image) { build(:image) } - let(:name_with_dash) { 'asd-asd' } - let(:name_with_slash) { 'asd/asd' } + let(:string_with_dash) { 'asd-asd' } + let(:string_with_slash) { 'asd/asd' } + let(:string_with_parenthesis) { 'centos 6.5 x86_64 (development instance)' } before do allow(Provider::ProviderFactory).to receive(:providers).and_return(%w(openstack ec2 static')) - allow_any_instance_of(Validators::Image::ImageInFilter).to receive(:available_images).and_return([{'id' => 'test_image'}, {'id' => name_with_dash}, {'id' => name_with_slash}]) + allow_any_instance_of(Validators::Image::ImageInFilter).to receive(:available_images).and_return([{'id' => 'test_image'}, {'id' => string_with_dash}, {'id' => string_with_slash}]) end it 'is valid with correct attrs' do @@ -21,16 +22,24 @@ RSpec.describe Devops::Model::Image, type: :model do include_examples 'field type validation', :bootstrap_template, :maybe_nil, :non_empty_string, :only_word_symbols, :field_validator it 'id should contain only letters, digits and dashes' do - expect(build(:image, id: name_with_dash)).to be_valid - expect(build(:image, id: name_with_slash)).not_to be_valid + expect(build(:image, id: string_with_dash)).to be_valid + expect(build(:image, id: string_with_slash)).not_to be_valid + expect(build(:image, id: string_with_parenthesis)).not_to be_valid end it "id should be included in image filters" do expect(build(:image, id: 'wrong')).not_to be_valid end - it 'name should contain only letters, digits and dashes' do - expect(build(:image, name: name_with_slash)).not_to be_valid + it 'name may contain everything' do + expect(build(:image, name: string_with_dash)).to be_valid + expect(build(:image, name: string_with_slash)).to be_valid + expect(build(:image, name: string_with_parenthesis)).to be_valid + end + + it 'name length should be less or equal than 100' do + expect(build(:image, name: 'a'*100)).to be_valid + expect(build(:image, name: 'a'*101)).not_to be_valid end it 'bootstrap_template should be included in available bootstrap templates' do