From 05e10e5784faa97e998f9b53af06608089749b5a Mon Sep 17 00:00:00 2001 From: Kyle Rames Date: Tue, 28 Jan 2014 16:01:51 -0600 Subject: [PATCH] [hp|compute_v2] added security group support --- lib/fog/hp/compute_v2.rb | 12 +++ .../hp/models/compute_v2/security_group.rb | 65 +++++++++++++++ .../hp/models/compute_v2/security_groups.rb | 29 +++++++ .../compute_v2/create_security_group.rb | 83 +++++++++++++++++++ .../compute_v2/create_security_group_rule.rb | 75 +++++++++++++++++ .../compute_v2/delete_security_group.rb | 41 +++++++++ .../compute_v2/delete_security_group_rule.rb | 49 +++++++++++ .../requests/compute_v2/get_security_group.rb | 57 +++++++++++++ .../compute_v2/list_security_groups.rb | 54 ++++++++++++ .../models/compute_v2/security_group_tests.rb | 40 +++++++++ .../compute_v2/security_groups_tests.rb | 7 ++ .../compute_v2/security_group_rule_tests.rb | 57 +++++++++++++ .../compute_v2/security_group_tests.rb | 67 +++++++++++++++ 13 files changed, 636 insertions(+) create mode 100644 lib/fog/hp/models/compute_v2/security_group.rb create mode 100644 lib/fog/hp/models/compute_v2/security_groups.rb create mode 100644 lib/fog/hp/requests/compute_v2/create_security_group.rb create mode 100644 lib/fog/hp/requests/compute_v2/create_security_group_rule.rb create mode 100644 lib/fog/hp/requests/compute_v2/delete_security_group.rb create mode 100644 lib/fog/hp/requests/compute_v2/delete_security_group_rule.rb create mode 100644 lib/fog/hp/requests/compute_v2/get_security_group.rb create mode 100644 lib/fog/hp/requests/compute_v2/list_security_groups.rb create mode 100644 tests/hp/models/compute_v2/security_group_tests.rb create mode 100644 tests/hp/models/compute_v2/security_groups_tests.rb create mode 100644 tests/hp/requests/compute_v2/security_group_rule_tests.rb create mode 100644 tests/hp/requests/compute_v2/security_group_tests.rb diff --git a/lib/fog/hp/compute_v2.rb b/lib/fog/hp/compute_v2.rb index 4e552ab9b..0cf0decf7 100644 --- a/lib/fog/hp/compute_v2.rb +++ b/lib/fog/hp/compute_v2.rb @@ -28,9 +28,12 @@ module Fog collection :metadata model :server collection :servers + model :security_group + collection :security_groups model :volume_attachment collection :volume_attachments + request_path 'fog/hp/requests/compute_v2' request :add_security_group request :allocate_address @@ -39,11 +42,16 @@ module Fog #request :confirm_resized_server request :create_image request :create_key_pair + request :create_security_group + request :create_security_group_rule request :create_server request :create_persistent_server request :delete_image request :delete_key_pair request :delete_meta + request :delete_security_group + request :delete_security_group_rule + request :create_security_group request :delete_server request :detach_volume request :disassociate_address @@ -54,6 +62,7 @@ module Fog request :get_key_pair request :get_meta request :get_windows_password + request :get_security_group request :get_server_details request :get_server_volume_details request :get_vnc_console @@ -66,6 +75,7 @@ module Fog request :list_key_pairs request :list_limits request :list_metadata + request :list_security_groups request :list_server_addresses request :list_server_addresses_by_network request :list_server_volumes @@ -134,12 +144,14 @@ module Fog :last_modified => { :images => {}, :key_pairs => {}, + :security_groups => {}, :servers => {}, :addresses => {}, :volume_attachments => {}, }, :images => {}, :key_pairs => {}, + :security_groups => {}, :servers => {}, :addresses => {}, :volume_attachments => {}, diff --git a/lib/fog/hp/models/compute_v2/security_group.rb b/lib/fog/hp/models/compute_v2/security_group.rb new file mode 100644 index 000000000..c85445dd5 --- /dev/null +++ b/lib/fog/hp/models/compute_v2/security_group.rb @@ -0,0 +1,65 @@ +require 'fog/core/model' + +module Fog + module Compute + class HPV2 + + class SecurityGroup < Fog::Model + + identity :id + + attribute :name + attribute :description + attribute :rules + attribute :tenant_id + + def destroy + requires :id + + service.delete_security_group(id) + true + end + + def save + requires :name, :description + + data = service.create_security_group(name, description) + merge_attributes(data.body['security_group']) + true + end + + def authorize_port_range(range, options = {}) + requires :id + + ip_protocol = options[:ip_protocol] || "tcp" + + if options[:group] + cidr = options[:cidr_ip] || "0.0.0.0/0" + else + group_id = options[:group].is_a?(SecurityGroup) ? options[:group].id : options[:group] + end + + service.create_security_group_rule(id, ip_protocol, range.min, range.max, cidr, group_id) + end + + + def create_rule(range, ip_protocol = "tcp", cidr = "0.0.0.0/0", group_id=nil) + requires :id + service.create_security_group_rule(id, ip_protocol, range.min, range.max, cidr, group_id) + end + + def delete_rule(rule_id) + service.delete_security_group_rule(rule_id) + true + end + + def delete_all_rules() + self.rules.each do |rule| + delete_rule(rule['id']) + end + true + end + end + end + end +end diff --git a/lib/fog/hp/models/compute_v2/security_groups.rb b/lib/fog/hp/models/compute_v2/security_groups.rb new file mode 100644 index 000000000..96a2e2f26 --- /dev/null +++ b/lib/fog/hp/models/compute_v2/security_groups.rb @@ -0,0 +1,29 @@ +require 'fog/core/collection' +require 'fog/hp/models/compute_v2/security_group' + +module Fog + module Compute + class HPV2 + + class SecurityGroups < Fog::Collection + + model Fog::Compute::HPV2::SecurityGroup + + def all + items = service.list_security_groups.body['security_groups'] + load(items) + end + + def get(security_group_id) + if security_group_id + sec_group = service.get_security_group(security_group_id).body['security_group'] + new(sec_group) + end + rescue Fog::Compute::HPV2::NotFound + nil + end + + end + end + end +end diff --git a/lib/fog/hp/requests/compute_v2/create_security_group.rb b/lib/fog/hp/requests/compute_v2/create_security_group.rb new file mode 100644 index 000000000..f78237dda --- /dev/null +++ b/lib/fog/hp/requests/compute_v2/create_security_group.rb @@ -0,0 +1,83 @@ +module Fog + module Compute + class HPV2 + class Real + + # Create a new security group + # + # ==== Parameters + # * 'name'<~String> - name of the security group + # * 'description'<~String> - description of the security group + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_group'<~Array>: + # * 'rules'<~Array>: - array of security group rules + # * 'id'<~Integer> - id of the security group rule + # * 'from_port'<~Integer> - start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'to_port'<~Integer> - end port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'ip_protocol'<~String> - ip protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'group'<~Hash>: + # * Undefined + # * 'parent_group_id'<~Integer> - parent group id + # * 'ip_range'<~Hash>: + # * 'cidr'<~String> - ip range address i.e. '0.0.0.0/0' + # * 'id'<~Integer> - id of the security group + # * 'name'<~String> - name of the security group + # * 'description'<~String> - description of the security group + # * 'tenant_id'<~String> - tenant id of the user + # + # {Openstack API Reference}[http://docs.openstack.org] + def create_security_group(name, description) + data = { + 'security_group' => { + 'name' => name, + 'description' => description + } + } + + request( + :body => Fog::JSON.encode(data), + :expects => 200, + :method => 'POST', + :path => 'os-security-groups.json' + ) + end + + end + + class Mock + + def create_security_group(name, description) + # all spaces are removed + name = name.strip + description = description.strip + + response = Excon::Response.new + if self.data[:security_groups].detect {|_,v| v['name'] == name} + response.status = 400 + response.body = { "badRequest" => {"message" => "Security group #{name} already exists", "code" => 400}} + raise(Excon::Errors.status_error({:expects => 200}, response)) + else + response.status = 200 + data = { + 'rules' => [], + 'id' => Fog::Mock.random_numbers(3).to_i, + 'tenant_id' => Fog::HP::Mock.user_id.to_s, + 'name' => name, + 'description' => description + } + self.data[:last_modified][:security_groups][data['id']] = Time.now + self.data[:security_groups][data['id']] = data + + response.body = { 'security_group' => data } + end + response + end + + end + + end + end +end diff --git a/lib/fog/hp/requests/compute_v2/create_security_group_rule.rb b/lib/fog/hp/requests/compute_v2/create_security_group_rule.rb new file mode 100644 index 000000000..f96f83e97 --- /dev/null +++ b/lib/fog/hp/requests/compute_v2/create_security_group_rule.rb @@ -0,0 +1,75 @@ +module Fog + module Compute + class HPV2 + class Real + + # Create a new security group rule and attach it to a security group + # + # ==== Parameters + # * 'parent_group_id'<~Integer> - id of the parent security group + # * 'ip_protocol'<~String> - ip protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'from_port'<~Integer> - start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'to_port'<~Integer> - end port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'cidr'<~String> - ip range address i.e. '0.0.0.0/0' + # * 'group_id'<~Integer> - id of the security group to which this rule applies + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # + # {Openstack API Reference}[http://docs.openstack.org] + def create_security_group_rule(parent_group_id, ip_protocol, from_port, to_port, cidr, group_id=nil) + data = { + 'security_group_rule' => { + 'parent_group_id' => parent_group_id, + 'ip_protocol' => ip_protocol, + 'from_port' => from_port, + 'to_port' => to_port, + 'cidr' => cidr, + 'group_id' => group_id + } + } + + request( + :body => Fog::JSON.encode(data), + :expects => 200, + :method => 'POST', + :path => 'os-security-group-rules.json' + ) + end + + end + + class Mock + + def create_security_group_rule(parent_group_id, ip_protocol, from_port, to_port, cidr, group_id=nil) + response = Excon::Response.new + group = self.data[:security_groups][parent_group_id] + if group + group['rules'] ||= [] + response.status = 200 + data = { + 'from_port' => from_port.to_i, + 'group' => {}, + 'ip_protocol' => ip_protocol, + 'to_port' => to_port.to_i, + 'parent_group_id' => parent_group_id, + 'ip_range' => { + 'cidr' => cidr + }, + 'id' => Fog::Mock.random_numbers(3).to_i + } + group['rules'][data['id']] = data + + response.body = { 'security_group_rule' => data } + response + else + raise Fog::Compute::HPV2::NotFound + end + end + + end + + end + end +end diff --git a/lib/fog/hp/requests/compute_v2/delete_security_group.rb b/lib/fog/hp/requests/compute_v2/delete_security_group.rb new file mode 100644 index 000000000..bd8751cd1 --- /dev/null +++ b/lib/fog/hp/requests/compute_v2/delete_security_group.rb @@ -0,0 +1,41 @@ +module Fog + module Compute + class HPV2 + class Real + + # Delete a security group + # + # ==== Parameters + # * id<~Integer> - Id of the security group to delete + # + # + # {Openstack API Reference}[http://docs.openstack.org] + def delete_security_group(security_group_id) + request( + :expects => 202, + :method => 'DELETE', + :path => "os-security-groups/#{security_group_id}" + ) + end + + end + + class Mock + + def delete_security_group(security_group_id) + response = Excon::Response.new + if self.data[:security_groups][security_group_id] + self.data[:last_modified][:security_groups].delete(security_group_id) + self.data[:security_groups].delete(security_group_id) + response.status = 202 + response.body = "202 Accepted\n\nThe request is accepted for processing.\n\n " + response + else + raise Fog::Compute::HPV2::NotFound + end + end + + end + end + end +end diff --git a/lib/fog/hp/requests/compute_v2/delete_security_group_rule.rb b/lib/fog/hp/requests/compute_v2/delete_security_group_rule.rb new file mode 100644 index 000000000..c1f067c23 --- /dev/null +++ b/lib/fog/hp/requests/compute_v2/delete_security_group_rule.rb @@ -0,0 +1,49 @@ +module Fog + module Compute + class HPV2 + class Real + + # Delete a security group rule + # + # ==== Parameters + # * id<~Integer> - id of the security group rule to delete + # + # {Openstack API Reference}[http://docs.openstack.org] + def delete_security_group_rule(security_group_rule_id) + request( + :expects => 202, + :method => 'DELETE', + :path => "os-security-group-rules/#{security_group_rule_id}" + ) + end + + end + + class Mock + + def delete_security_group_rule(security_group_rule_id) + response = Excon::Response.new + + sg_rule = nil + + self.data[:security_groups].each do |_, sgv| + if sgv['rules'] + sg_rule = sgv['rules'].delete_if { |r| !r.nil? && r['id'] == security_group_rule_id } + break if sg_rule + end + end + + if sg_rule && !sg_rule.empty? + response.status = 202 + response.body = "202 Accepted\n\nThe request is accepted for processing.\n\n " + response + else + raise Fog::Compute::HPV2::NotFound + end + + end + + end + end + end +end diff --git a/lib/fog/hp/requests/compute_v2/get_security_group.rb b/lib/fog/hp/requests/compute_v2/get_security_group.rb new file mode 100644 index 000000000..f22b54ece --- /dev/null +++ b/lib/fog/hp/requests/compute_v2/get_security_group.rb @@ -0,0 +1,57 @@ +module Fog + module Compute + class HPV2 + class Real + + # Get details about a security group + # + # ==== Parameters + # * 'security_group_id'<~Integer> - Id of security group to get details for + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_group'<~Array>: + # * 'rules'<~Array>: - array of security group rules + # * 'id'<~Integer> - id of the security group rule + # * 'from_port'<~Integer> - start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'to_port'<~Integer> - end port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'ip_protocol'<~String> - ip protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'group'<~Hash>: + # * Undefined + # * 'parent_group_id'<~Integer> - parent group id + # * 'ip_range'<~Hash>: + # * 'cidr'<~String> - ip range address i.e. '0.0.0.0/0' + # * 'id'<~Integer> - id of the security group + # * 'name'<~String> - name of the security group + # * 'description'<~String> - description of the security group + # * 'tenant_id'<~String> - tenant id of the user + # + # {Openstack API Reference}[http://docs.openstack.org] + def get_security_group(security_group_id) + request( + :expects => [200], + :method => 'GET', + :path => "os-security-groups/#{security_group_id}" + ) + end + + end + + class Mock + + def get_security_group(security_group_id) + response = Excon::Response.new + if sec_group = self.data[:security_groups][security_group_id] + response.status = 200 + response.body = { 'security_group' => sec_group } + response + else + raise Fog::Compute::HPV2::NotFound + end + end + + end + end + end +end diff --git a/lib/fog/hp/requests/compute_v2/list_security_groups.rb b/lib/fog/hp/requests/compute_v2/list_security_groups.rb new file mode 100644 index 000000000..827859c1e --- /dev/null +++ b/lib/fog/hp/requests/compute_v2/list_security_groups.rb @@ -0,0 +1,54 @@ +module Fog + module Compute + class HPV2 + class Real + + # List all security groups + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_groups'<~Array>: + # * 'rules'<~Array>: - array of security group rules + # * 'id'<~Integer> - id of the security group rule + # * 'from_port'<~Integer> - start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'to_port'<~Integer> - end port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'ip_protocol'<~String> - ip protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'group'<~Hash>: + # * Undefined + # * 'parent_group_id'<~Integer> - parent group id + # * 'ip_range'<~Hash>: + # * 'cidr'<~String> - ip range address i.e. '0.0.0.0/0' + # * 'id'<~Integer> - id of the security group + # * 'name'<~String> - name of the security group + # * 'description'<~String> - description of the security group + # * 'tenant_id'<~String> - tenant id of the user + # + # {Openstack API Reference}[http://docs.openstack.org] + def list_security_groups + request( + :expects => [200], + :method => 'GET', + :path => 'os-security-groups.json' + ) + end + + end + + class Mock + + def list_security_groups + response = Excon::Response.new + + sec_groups = [] + sec_groups = self.data[:security_groups].values unless self.data[:security_groups].nil? + + response.status = 200 + response.body = { 'security_groups' => sec_groups } + response + end + + end + end + end +end diff --git a/tests/hp/models/compute_v2/security_group_tests.rb b/tests/hp/models/compute_v2/security_group_tests.rb new file mode 100644 index 000000000..53e803db4 --- /dev/null +++ b/tests/hp/models/compute_v2/security_group_tests.rb @@ -0,0 +1,40 @@ +Shindo.tests("Fog::Compute::HPV2 | security_group", ['hp']) do + # Disabled due to https://github.com/fog/fog/1546 + pending + + service = Fog::Compute.new(:provider => 'HP', :version => :v2) + + model_tests(service.security_groups, {:name => 'foggroupname', :description => 'foggroupdescription'}, true) + + tests("a group with trailing whitespace") do + @group = service.security_groups.create(:name => " foggroup with spaces ", :description => " fog group desc ") + + test("all spaces are removed from name") do + @group.name == " foggroup with spaces ".strip! + end + + test("all spaces are removed from description") do + @group.description == " fog group desc ".strip! + end + + @other_group = service.security_groups.create(:name => 'other group', :description => 'another group') + + test("authorize access by another security group") do + sgrule = @group.create_rule(80..80, "tcp", nil, @other_group.id) + @sg_rule_id = sgrule.body['security_group_rule']['id'] + @group.reload + s = @group.rules.select {|r| r['id'] == @sg_rule_id unless r.nil?} + s[0]['id'] == @sg_rule_id + end + + test("revoke access from another security group") do + @group.delete_rule(@sg_rule_id) + @group.reload + s = @group.rules.select {|r| r['id'] == @sg_rule_id unless r.nil?} + s.empty? + end + + @other_group.destroy + @group.destroy + end +end diff --git a/tests/hp/models/compute_v2/security_groups_tests.rb b/tests/hp/models/compute_v2/security_groups_tests.rb new file mode 100644 index 000000000..ea9c7feee --- /dev/null +++ b/tests/hp/models/compute_v2/security_groups_tests.rb @@ -0,0 +1,7 @@ +Shindo.tests("Fog::Compute::HPV2| security_groups", ['hp']) do + + service = Fog::Compute.new(:provider => 'HP', :version => :v2) + + collection_tests(service.security_groups, {:name => 'foggroupname', :description => 'foggroupdescription'}, true) + +end diff --git a/tests/hp/requests/compute_v2/security_group_rule_tests.rb b/tests/hp/requests/compute_v2/security_group_rule_tests.rb new file mode 100644 index 000000000..59bd562db --- /dev/null +++ b/tests/hp/requests/compute_v2/security_group_rule_tests.rb @@ -0,0 +1,57 @@ +Shindo.tests("Fog::Compute::HPV2 | security group requests", ['hp']) do + + @security_group_rule_format = { + 'from_port' => Integer, + 'group' => Fog::Nullable::Hash, + 'ip_protocol' => String, + 'to_port' => Integer, + 'parent_group_id' => Integer, + 'ip_range' => { + 'cidr' => String + }, + 'id' => Integer + } + + service = Fog::Compute.new(:provider => 'HP', :version => :v2) + + + tests('success') do + @security_group =service.security_groups.create(:name => 'fog_security_group', :description => 'tests group') + + tests("tcp #create_security_group_rule('#{@security_group.id}', 'tcp', '80', '80', '0.0.0.0/0'}')").formats({'security_group_rule' => @security_group_rule_format}) do + data =service.create_security_group_rule(@security_group.id, 'tcp', '80', '80', '0.0.0.0/0').body + @sec_group_rule_id_1 = data['security_group_rule']['id'] + data + end + + tests("icmp #create_security_group_rule('#{@security_group.id}', 'icmp', '-1', '-1', '0.0.0.0/0'}')").formats({'security_group_rule' => @security_group_rule_format}) do + data =service.create_security_group_rule(@security_group.id, 'icmp', '-1', '-1', '0.0.0.0/0').body + @sec_group_rule_id_2 = data['security_group_rule']['id'] + data + end + + tests("tcp #delete_security_group_rule('#{@sec_group_rule_id_1}')").succeeds do + service.delete_security_group_rule(@sec_group_rule_id_1).body + end + + tests("icmp #delete_security_group_rule('#{@sec_group_rule_id_2}')").succeeds do + service.delete_security_group_rule(@sec_group_rule_id_2).body + end + + @security_group.destroy + + end + + tests('failure') do + + tests("#create_security_group_rule(0, 'tcp', '80', '80', '0.0.0.0/0'}')").raises(Fog::Compute::HPV2::NotFound) do + service.create_security_group_rule(0, 'tcp', '80', '80', '0.0.0.0/0') + end + + tests("#delete_security_group_rule(0)").raises(Fog::Compute::HPV2::NotFound) do + service.delete_security_group_rule(0) + end + + end + +end diff --git a/tests/hp/requests/compute_v2/security_group_tests.rb b/tests/hp/requests/compute_v2/security_group_tests.rb new file mode 100644 index 000000000..489d90622 --- /dev/null +++ b/tests/hp/requests/compute_v2/security_group_tests.rb @@ -0,0 +1,67 @@ +Shindo.tests("Fog::Compute::HPV2 | security group requests", ['hp']) do + + @security_groups_format = { + 'security_groups' => [{ + 'rules' => [Fog::Nullable::Hash], + 'tenant_id' => String, + 'id' => Integer, + 'name' => String, + 'description' => String + }] + } + + @security_group_format = { + 'rules' => [Fog::Nullable::Hash], + 'tenant_id' => String, + 'id' => Integer, + 'name' => String, + 'description' => String + } + + service = Fog::Compute.new(:provider => 'HP', :version => :v2) + + + tests('success') do + + tests("#create_security_group('fog_security_group', 'tests group')").formats({'security_group' => @security_group_format}) do + data =service.create_security_group('fog_security_group', 'tests group').body + @sec_group_id = data['security_group']['id'] + data + end + + tests("#get_security_group('#{@sec_group_id}')").formats({'security_group' => @security_group_format}) do + service.get_security_group(@sec_group_id).body + end + + tests("#list_security_groups").formats(@security_groups_format) do + service.list_security_groups.body + end + + + tests("#delete_security_group('#{@sec_group_id}')").succeeds do + service.delete_security_group(@sec_group_id).body + end + + end + + tests('failure') do + + @security_group =service.security_groups.create(:name => 'fog_security_group_fail', :description => 'tests group') + + tests("duplicate #create_security_group(#{@security_group.name}, #{@security_group.description})").raises(Excon::Errors::BadRequest) do + service.create_security_group(@security_group.name, @security_group.description) + end + + tests("#get_security_group(0)").raises(Fog::Compute::HPV2::NotFound) do + service.get_security_group(0) + end + + tests("#delete_security_group(0)").raises(Fog::Compute::HPV2::NotFound) do + service.delete_security_group(0) + end + + @security_group.destroy + + end + +end