diff --git a/lib/fog/openstack/models/network/network.rb b/lib/fog/openstack/models/network/network.rb index 1cf80eaac9..ab88f5e338 100644 --- a/lib/fog/openstack/models/network/network.rb +++ b/lib/fog/openstack/models/network/network.rb @@ -12,14 +12,10 @@ class Network < Fog::Model attribute :status attribute :admin_state_up attribute :tenant_id - attribute :provider_network_type, - :aliases => 'provider:network_type' - attribute :provider_physical_network, - :aliases => 'provider:physical_network' - attribute :provider_segmentation_id, - :aliases => 'provider:segmentation_id' - attribute :router_external, - :aliases => 'router:external' + attribute :provider_network_type, :aliases => 'provider:network_type' + attribute :provider_physical_network, :aliases => 'provider:physical_network' + attribute :provider_segmentation_id, :aliases => 'provider:segmentation_id' + attribute :router_external, :aliases => 'router:external' def initialize(attributes) # Old 'connection' is renamed as service and should be used instead @@ -31,6 +27,10 @@ def save identity ? update : create end + def subnets + service.subnets.select {|s| s.network_id == self.id } + end + def create merge_attributes(service.create_network(self.attributes).body['network']) self @@ -38,8 +38,7 @@ def create def update requires :id - merge_attributes(service.update_network(self.id, - self.attributes).body['network']) + merge_attributes(service.update_network(self.id, self.attributes).body['network']) self end @@ -48,7 +47,6 @@ def destroy service.delete_network(self.id) true end - end end end diff --git a/lib/fog/openstack/models/network/security_group.rb b/lib/fog/openstack/models/network/security_group.rb new file mode 100644 index 0000000000..a36bf977e6 --- /dev/null +++ b/lib/fog/openstack/models/network/security_group.rb @@ -0,0 +1,32 @@ +require 'fog/core/model' + +module Fog + module Network + class OpenStack + class SecurityGroup < Fog::Model + identity :id + + attribute :name + attribute :description + attribute :security_group_rules + attribute :tenant_id + + def destroy + requires :id + service.delete_security_group(id) + true + end + + def security_group_rules + Fog::Network::OpenStack::SecurityGroupRules.new(:service => service).load(attributes[:security_group_rules]) + end + + def save + raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted? + merge_attributes(service.create_security_group(attributes).body['security_group']) + true + end + end + end + end +end diff --git a/lib/fog/openstack/models/network/security_group_rule.rb b/lib/fog/openstack/models/network/security_group_rule.rb new file mode 100644 index 0000000000..f59d177354 --- /dev/null +++ b/lib/fog/openstack/models/network/security_group_rule.rb @@ -0,0 +1,33 @@ +require 'fog/core/model' + +module Fog + module Network + class OpenStack + class SecurityGroupRule < Fog::Model + identity :id + + attribute :security_group_id + attribute :direction + attribute :protocol + attribute :port_range_min + attribute :port_range_max + attribute :remote_ip_prefix + attribute :ethertype + attribute :remote_group_id + attribute :tenant_id + + def destroy + requires :id + service.delete_security_group_rule(id) + true + end + + def save + raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted? + merge_attributes(service.create_security_group_rule(security_group_id, direction, attributes).body['security_group_rule']) + true + end + end + end + end +end diff --git a/lib/fog/openstack/models/network/security_group_rules.rb b/lib/fog/openstack/models/network/security_group_rules.rb new file mode 100644 index 0000000000..55336363f2 --- /dev/null +++ b/lib/fog/openstack/models/network/security_group_rules.rb @@ -0,0 +1,33 @@ +require 'fog/core/collection' +require 'fog/openstack/models/network/security_group_rule' + +module Fog + module Network + class OpenStack + class SecurityGroupRules < Fog::Collection + + attribute :filters + + model Fog::Network::OpenStack::SecurityGroupRule + + def initialize(attributes) + self.filters ||= {} + super + end + + def all(filters = filters) + self.filters = filters + load(service.list_security_group_rules(filters).body['security_group_rules']) + end + + def get(sec_group_rule_id) + if sec_group_rule = service.get_security_group_rule(sec_group_rule_id).body['security_group_rule'] + new(sec_group_rule) + end + rescue Fog::Network::OpenStack::NotFound + nil + end + end + end + end +end diff --git a/lib/fog/openstack/models/network/security_groups.rb b/lib/fog/openstack/models/network/security_groups.rb new file mode 100644 index 0000000000..7a96ff5994 --- /dev/null +++ b/lib/fog/openstack/models/network/security_groups.rb @@ -0,0 +1,34 @@ +require 'fog/core/collection' +require 'fog/openstack/models/network/security_group' + +module Fog + module Network + class OpenStack + class SecurityGroups < Fog::Collection + + attribute :filters + + model Fog::Network::OpenStack::SecurityGroup + + def initialize(attributes) + self.filters ||= {} + super + end + + def all(filters = filters) + self.filters = filters + load(service.list_security_groups(filters).body['security_groups']) + end + + def get(security_group_id) + if security_group = service.get_security_group(security_group_id).body['security_group'] + new(security_group) + end + rescue Fog::Network::OpenStack::NotFound + nil + end + + end + end + end +end diff --git a/lib/fog/openstack/network.rb b/lib/fog/openstack/network.rb index 1cd6f92f78..738e8e1bfe 100644 --- a/lib/fog/openstack/network.rb +++ b/lib/fog/openstack/network.rb @@ -32,6 +32,10 @@ class OpenStack < Fog::Service collection :lb_health_monitors model :lb_vip collection :lb_vips + model :security_group + collection :security_groups + model :security_group_rule + collection :security_group_rules ## REQUESTS # @@ -106,6 +110,18 @@ class OpenStack < Fog::Service request :get_lb_vip request :update_lb_vip + # Security Group + request :create_security_group + request :delete_security_group + request :get_security_group + request :list_security_groups + + # Security Group Rules + request :create_security_group_rule + request :delete_security_group_rule + request :get_security_group_rule + request :list_security_group_rules + # Tenant request :set_tenant @@ -175,6 +191,8 @@ def self.data "port" => 30 } ], + :security_groups => {}, + :security_group_rules => {}, } end end diff --git a/lib/fog/openstack/orchestration.rb b/lib/fog/openstack/orchestration.rb index 1bd744da14..6726a378f3 100644 --- a/lib/fog/openstack/orchestration.rb +++ b/lib/fog/openstack/orchestration.rb @@ -20,6 +20,9 @@ class OpenStack < Fog::Service request :update_stack request :delete_stack request :list_stacks + request :describe_stack + request :get_template + request :list_stack_resources class Mock attr_reader :auth_token @@ -30,7 +33,10 @@ class Mock def self.data @data ||= Hash.new do |hash, key| hash[key] = { - :stacks => {} + :stacks => {}, + :stack_details => {}, + :resources => {}, + :templates => {} } end end diff --git a/lib/fog/openstack/requests/network/create_security_group.rb b/lib/fog/openstack/requests/network/create_security_group.rb new file mode 100644 index 0000000000..39c0932316 --- /dev/null +++ b/lib/fog/openstack/requests/network/create_security_group.rb @@ -0,0 +1,94 @@ +module Fog + module Network + class OpenStack + class Real + # Create a new security group + # + # ==== Parameters + # * options<~Hash>: + # * 'name'<~String> - Name of the security group + # * 'description'<~String> - Description of the security group + # * 'tenant_id'<~String> - TenantId different than the current user, that should own the security group. Only allowed if user has 'admin' role. + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_groups'<~Array>: + # * 'id'<~String> - UUID of the security group + # * 'name'<~String> - Name of the security group + # * 'description'<~String> - Description of the security group + # * 'tenant_id'<~String> - Tenant id that owns the security group + # * 'security_group_rules'<~Array>: - Array of security group rules + # * 'id'<~String> - UUID of the security group rule + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * 'port_range_min'<~Integer> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~Integer> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'remote_group_id'<~String> - UUID of the remote security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - Tenant id that owns the security group rule + def create_security_group(options = {}) + data = {"security_group" => {}} + desired_options = [:name, :description, :tenant_id] + selected_options = desired_options.select{|o| options[o]} + selected_options.each { |key| data["security_group"][key] = options[key] } + + request( + :body => Fog::JSON.encode(data), + :expects => 201, + :method => "POST", + :path => "security-groups" + ) + end + end + + class Mock + def create_security_group(options = {}) + # Spaces are NOT removed from name and description, as in case of compute sec groups + tenant_id = Fog::Mock.random_numbers(14).to_s + sec_group_id = Fog::UUID.uuid + + response = Excon::Response.new + response.status = 201 + # by default every security group will come setup with an egress rule to "allow all out" + data = { + "security_group_rules" => [ + { "remote_group_id" => nil, + "direction" => "egress", + "remote_ip_prefix" => nil, + "protocol" => nil, + "ethertype" => "IPv4", + "tenant_id" => tenant_id, + "port_range_max" => nil, + "port_range_min" => nil, + "id" => Fog::UUID.uuid, + "security_group_id" => sec_group_id + }, + { "remote_group_id" => nil, + "direction" => "egress", + "remote_ip_prefix" => nil, + "protocol" => nil, + "ethertype" => "IPv6", + "tenant_id" => tenant_id, + "port_range_max" => nil, + "port_range_min" => nil, + "id" => Fog::UUID.uuid, + "security_group_id" => sec_group_id + } + ], + "id" => sec_group_id, + "tenant_id" => tenant_id, + "name" => options[:name] || "", + "description" => options[:description] || "" + } + + self.data[:security_groups][data["id"]] = data + response.body = {"security_group" => data} + response + end + end + end + end +end diff --git a/lib/fog/openstack/requests/network/create_security_group_rule.rb b/lib/fog/openstack/requests/network/create_security_group_rule.rb new file mode 100644 index 0000000000..9aee83a932 --- /dev/null +++ b/lib/fog/openstack/requests/network/create_security_group_rule.rb @@ -0,0 +1,79 @@ +module Fog + module Network + class OpenStack + class Real + # Create a new security group rule + # + # ==== Parameters + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * options<~Hash>: + # * 'port_range_min'<~Integer> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~Integer> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'remote_group_id'<~String> - UUID of the remote security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - TenantId different than the current user, that should own the security group. Only allowed if user has 'admin' role. + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_group_rule'<~Hash>: + # * 'id'<~String> - UUID of the security group rule + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * 'port_range_min'<~String> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~String> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'remote_group_id'<~String> - UUID of the source security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - Tenant id that owns the security group rule + def create_security_group_rule(security_group_id, direction, options = {}) + data = {"security_group_rule" => {"security_group_id" => security_group_id, "direction" => direction}} + desired_options = [ + :port_range_min, + :port_range_max, + :protocol, + :ethertype, + :remote_group_id, + :remote_ip_prefix, + :tenant_id + ] + selected_options = desired_options.select{ |o| options[o] } + selected_options.each { |key| data["security_group_rule"][key] = options[key] } + + request( + :body => Fog::JSON.encode(data), + :expects => 201, + :method => "POST", + :path => "security-group-rules" + ) + end + end + + class Mock + def create_security_group_rule(security_group_id, direction, options = {}) + response = Excon::Response.new + data = { + "id" => Fog::UUID.uuid, + "remote_group_id" => options[:remote_group_id], + "direction" => direction, + "remote_ip_prefix" => options[:remote_ip_prefix], + "protocol" => options[:protocol], + "ethertype" => options[:ethertype] || "IPv4", + "tenant_id" => options[:tenant_id] || Fog::Mock.random_numbers(14).to_s, + "port_range_max" => options[:port_range_max], + "port_range_min" => options[:port_range_min], + "security_group_id" => security_group_id + } + self.data[:security_group_rules][data["id"]] = data + response.status = 201 + response.body = {"security_group_rule" => data} + response + end + end + end + end +end diff --git a/lib/fog/openstack/requests/network/delete_security_group.rb b/lib/fog/openstack/requests/network/delete_security_group.rb new file mode 100644 index 0000000000..895b452359 --- /dev/null +++ b/lib/fog/openstack/requests/network/delete_security_group.rb @@ -0,0 +1,32 @@ +module Fog + module Network + class OpenStack + class Real + # Delete a security group + # + # ==== Parameters + # * 'security_group_id'<~String> - UUID of the security group to delete + def delete_security_group(security_group_id) + request( + :expects => 204, + :method => 'DELETE', + :path => "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[:security_groups].delete(security_group_id) + response.status = 204 + response + else + raise Fog::Network::OpenStack::NotFound + end + end + end + end + end +end diff --git a/lib/fog/openstack/requests/network/delete_security_group_rule.rb b/lib/fog/openstack/requests/network/delete_security_group_rule.rb new file mode 100644 index 0000000000..2b0b024031 --- /dev/null +++ b/lib/fog/openstack/requests/network/delete_security_group_rule.rb @@ -0,0 +1,36 @@ +module Fog + module Network + class OpenStack + class Real + + # Delete a security group rule + # + # ==== Parameters + # * 'security_group_rule_id'<~String> - UUID of the security group rule to delete + def delete_security_group_rule(security_group_rule_id) + request( + :expects => 204, + :method => "DELETE", + :path => "security-group-rules/#{security_group_rule_id}" + ) + end + + end + + class Mock + + def delete_security_group_rule(security_group_rule_id) + response = Excon::Response.new + if self.data[:security_group_rules][security_group_rule_id] + self.data[:security_group_rules].delete(security_group_rule_id) + response.status = 204 + response + else + raise Fog::Network::OpenStack::NotFound + end + end + + end + end + end +end diff --git a/lib/fog/openstack/requests/network/get_security_group.rb b/lib/fog/openstack/requests/network/get_security_group.rb new file mode 100644 index 0000000000..366539d7f6 --- /dev/null +++ b/lib/fog/openstack/requests/network/get_security_group.rb @@ -0,0 +1,52 @@ +module Fog + module Network + class OpenStack + class Real + # Get details about a security group + # + # ==== Parameters + # * 'security_group_id'<~String> - UUID of the security group + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_group'<~Array>: + # * 'id'<~String> - UUID of the security group + # * 'name'<~String> - Name of the security group + # * 'description'<~String> - Description of the security group + # * 'tenant_id'<~String> - Tenant id that owns the security group + # * 'security_group_rules'<~Array>: - Array of security group rules + # * 'id'<~String> - UUID of the security group rule + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * 'port_range_min'<~Integer> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~Integer> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'remote_group_id'<~String> - UUID of the remote security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - Tenant id that owns the security group rule + def get_security_group(security_group_id) + request( + :expects => 200, + :method => "GET", + :path => "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::Network::OpenStack::NotFound + end + end + end + end + end +end diff --git a/lib/fog/openstack/requests/network/get_security_group_rule.rb b/lib/fog/openstack/requests/network/get_security_group_rule.rb new file mode 100644 index 0000000000..1bef89098c --- /dev/null +++ b/lib/fog/openstack/requests/network/get_security_group_rule.rb @@ -0,0 +1,47 @@ +module Fog + module Network + class OpenStack + class Real + # Get details about a security group rule + # + # ==== Parameters + # * 'security_group_rule_id'<~String> - UUID of the security group rule + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_group_rule'<~Hash>: + # * 'id'<~String> - UUID of the security group rule + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * 'port_range_min'<~Integer> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~Integer> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'remote_group_id'<~String> - UUID of the remote security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - Tenant id that owns the security group rule + def get_security_group_rule(security_group_rule_id) + request( + :expects => 200, + :method => "GET", + :path => "security-group-rules/#{security_group_rule_id}" + ) + end + end + + class Mock + def get_security_group_rule(security_group_rule_id) + response = Excon::Response.new + if sec_group_rule = self.data[:security_group_rules][security_group_rule_id] + response.status = 200 + response.body = {"security_group_rule" => sec_group_rule} + response + else + raise Fog::Network::OpenStack::NotFound + end + end + end + end + end +end diff --git a/lib/fog/openstack/requests/network/list_networks.rb b/lib/fog/openstack/requests/network/list_networks.rb index bb8df2fbae..42c6b8663e 100644 --- a/lib/fog/openstack/requests/network/list_networks.rb +++ b/lib/fog/openstack/requests/network/list_networks.rb @@ -1,7 +1,6 @@ module Fog module Network class OpenStack - class Real def list_networks(filters = {}) request( diff --git a/lib/fog/openstack/requests/network/list_security_group_rules.rb b/lib/fog/openstack/requests/network/list_security_group_rules.rb new file mode 100644 index 0000000000..4af07fdb63 --- /dev/null +++ b/lib/fog/openstack/requests/network/list_security_group_rules.rb @@ -0,0 +1,52 @@ +module Fog + module Network + class OpenStack + class Real + + # List all security group rules + # + # ==== Parameters + # * options<~Hash>: + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_group_rules'<~Array>: + # * 'id'<~String> - UUID of the security group rule + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * 'port_range_min'<~Integer> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~Integer> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'remote_group_id'<~String> - UUID of the remote security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - Tenant id that owns the security group rule + def list_security_group_rules(options = {}) + request( + :expects => 200, + :method => 'GET', + :path => 'security-group-rules', + :query => options + ) + end + + end + + class Mock + + def list_security_group_rules(options = {}) + response = Excon::Response.new + + sec_group_rules = [] + sec_group_rules = self.data[:security_group_rules].values unless self.data[:security_group_rules].nil? + + response.status = 200 + response.body = { 'security_group_rules' => sec_group_rules } + response + end + + end + end + end +end diff --git a/lib/fog/openstack/requests/network/list_security_groups.rb b/lib/fog/openstack/requests/network/list_security_groups.rb new file mode 100644 index 0000000000..b0bbd2c4bc --- /dev/null +++ b/lib/fog/openstack/requests/network/list_security_groups.rb @@ -0,0 +1,57 @@ +module Fog + module Network + class OpenStack + class Real + + # List all security groups + # + # ==== Parameters + # * options<~Hash>: + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_groups'<~Array>: + # * 'id'<~String> - UUID of the security group + # * 'name'<~String> - Name of the security group + # * 'description'<~String> - Description of the security group + # * 'tenant_id'<~String> - Tenant id that owns the security group + # * 'security_group_rules'<~Array>: - Array of security group rules + # * 'id'<~String> - UUID of the security group rule + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * 'port_range_min'<~Integer> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~Integer> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'remote_group_id'<~String> - UUID of the remote security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - Tenant id that owns the security group rule + def list_security_groups(options = {}) + request( + :expects => 200, + :method => 'GET', + :path => 'security-groups', + :query => options + ) + end + + end + + class Mock + + def list_security_groups(options = {}) + 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/lib/fog/openstack/requests/orchestration/create_stack.rb b/lib/fog/openstack/requests/orchestration/create_stack.rb index ade690582c..4a5e95ddfa 100644 --- a/lib/fog/openstack/requests/orchestration/create_stack.rb +++ b/lib/fog/openstack/requests/orchestration/create_stack.rb @@ -45,6 +45,30 @@ def create_stack(stack_name, options = {}) 'updated_time' => Time.now } + self.data[:stack_details][stack_name] ||= {} + self.data[:stack_details][stack_name][stack_id] = stack.merge ({ + 'parameters' => options[:parameters], + 'output' => [], + 'disable_rollback' => options[:disable_rollback] + }) + + self.data[:templates][stack_name] ||= {} + self.data[:templates][stack_name][stack_id] = options[:template_body] + + self.data[:resources][stack_name] ||= {} + self.data[:resources][stack_name][stack_id] = [ + { 'resource_name' => 'my_instance', + 'links' => [], + 'logical_resource_id' => 'my_instance', + 'resource_status_reason' => 'state changed', + 'updated_time' => Time.now, + 'required_by' => [], + 'resource_status' => 'CREATE_COMPLETE', + 'physical_resource_id' => Fog::Mock.random_hex(32), + 'resource_type' => 'OS::Nova::Server' + } + ] + response = Excon::Response.new response.status = 201 response.body = { diff --git a/lib/fog/openstack/requests/orchestration/describe_stack.rb b/lib/fog/openstack/requests/orchestration/describe_stack.rb new file mode 100644 index 0000000000..5fbd7248fb --- /dev/null +++ b/lib/fog/openstack/requests/orchestration/describe_stack.rb @@ -0,0 +1,32 @@ +module Fog + module Orchestration + class OpenStack + class Real + # Describe a specified stack + # + # @param stack_name [String] stack name to get details from + # @param stack_id [String] the unique identifier for the stack + # + # @return [Excon::Response] + + def describe_stack(stack_name, stack_id) + request( + :expects => 200, + :path => "stacks/#{stack_name}/#{stack_id}", + :method => 'GET' + ) + end + end + + class Mock + def describe_stack(stack_name, stack_id) + stack = self.data[:stack_details][stack_name][stack_id] + Excon::Response.new( + :body => { 'stack' => stack }, + :status => 200 + ) + end + end + end + end +end diff --git a/lib/fog/openstack/requests/orchestration/get_template.rb b/lib/fog/openstack/requests/orchestration/get_template.rb new file mode 100644 index 0000000000..744b86228c --- /dev/null +++ b/lib/fog/openstack/requests/orchestration/get_template.rb @@ -0,0 +1,34 @@ +module Fog + module Orchestration + class OpenStack + class Real + # Get the template for a specified stack + # + # @param stack_name [String] stack name to get template from + # @param stack_id [String] the unique identifier for the stack + # + # @return [Excon::Response] + # * body [Hash]: + # * TemplateBody [String] - + # + def get_template(stack_name, stack_id) + request( + :expects => 200, + :path => "stacks/#{stack_name}/#{stack_id}/template", + :method => 'GET' + ) + end + end + + class Mock + def get_template(stack_name, stack_id) + template = self.data[:templates][stack_name][stack_id] + Excon::Response.new( + :body => template, + :status => 200 + ) + end + end + end + end +end diff --git a/lib/fog/openstack/requests/orchestration/list_stack_resources.rb b/lib/fog/openstack/requests/orchestration/list_stack_resources.rb new file mode 100644 index 0000000000..a68d6dfe1e --- /dev/null +++ b/lib/fog/openstack/requests/orchestration/list_stack_resources.rb @@ -0,0 +1,36 @@ +module Fog + module Orchestration + class OpenStack + class Real + # List resources from a specified stack + # + # @param stack_name [String] stack name to get resources from + # @param stack_id [String] the unique identifier for the stack + # @param options [Hash] + # * nested_depth - also includes resources from nested stacks up to nested_depth + # levels of recursion. + # + # @return [Excon::Response] + + def list_stack_resources(stack_name, stack_id, options = {}) + request( + :expects => 200, + :path => "stacks/#{stack_name}/#{stack_id}/resources", + :method => 'GET', + :query => options + ) + end + end + + class Mock + def list_stack_resources(stack_name, stack_id, options = {}) + resources = self.data[:resources][stack_name][stack_id] + Excon::Response.new( + :body => { 'resources' => resources }, + :status => 200 + ) + end + end + end + end +end diff --git a/tests/openstack/models/network/security_group_rule_tests.rb b/tests/openstack/models/network/security_group_rule_tests.rb new file mode 100644 index 0000000000..81ef96b25d --- /dev/null +++ b/tests/openstack/models/network/security_group_rule_tests.rb @@ -0,0 +1,27 @@ +Shindo.tests('Fog::Network[:openstack] | security_group_rule model', ['openstack']) do + + @secgroup = Fog::Network[:openstack].security_groups.create({:name => "fogsecgroup"}) + attributes = {:security_group_id => @secgroup.id, :direction => "ingress"} + model_tests(Fog::Network[:openstack].security_group_rules, attributes, true) + + tests('success') do + tests('#create').succeeds do + attributes = { + :security_group_id => @secgroup.id, + :direction => "ingress", + :protocol => "tcp", + :port_range_min => 22, + :port_range_max => 22, + :remote_ip_prefix => "0.0.0.0/0" + } + @secgrouprule = Fog::Network[:openstack].security_group_rules.create(attributes) + @secgrouprule.wait_for { ready? } unless Fog.mocking? + !@secgrouprule.id.nil? + end + + tests('#destroy').succeeds do + @secgrouprule.destroy + end + end + @secgroup.destroy +end diff --git a/tests/openstack/models/network/security_group_rules_tests.rb b/tests/openstack/models/network/security_group_rules_tests.rb new file mode 100644 index 0000000000..c5eacddea4 --- /dev/null +++ b/tests/openstack/models/network/security_group_rules_tests.rb @@ -0,0 +1,25 @@ +Shindo.tests('Fog::Network[:openstack] | security_group_rules collection', ['openstack']) do + + @secgroup = Fog::Network[:openstack].security_groups.create({:name => "my_secgroup"}) + attributes = {:security_group_id => @secgroup.id, :direction => "ingress"} + collection_tests(Fog::Network[:openstack].security_group_rules, attributes, true) + + tests('success') do + attributes = { + :security_group_id => @secgroup.id, + :direction => "ingress", + :protocol => "tcp", + :port_range_min => 22, + :port_range_max => 22, + :remote_ip_prefix => "0.0.0.0/0" + } + @secgrouprule = Fog::Network[:openstack].security_group_rules.create(attributes) + + tests('#all(filter)').succeeds do + secgrouprule = Fog::Network[:openstack].security_group_rules.all({:direction => "ingress"}) + secgrouprule.first.direction == "ingress" + end + @secgrouprule.destroy + end + @secgroup.destroy +end diff --git a/tests/openstack/models/network/security_group_tests.rb b/tests/openstack/models/network/security_group_tests.rb new file mode 100644 index 0000000000..4030cb8a63 --- /dev/null +++ b/tests/openstack/models/network/security_group_tests.rb @@ -0,0 +1,17 @@ +Shindo.tests('Fog::Network[:openstack] | security_group model', ['openstack']) do + + model_tests(Fog::Network[:openstack].security_groups, {:name => "fogsecgroup"}, true) + + tests('success') do + tests('#create').succeeds do + attributes = {:name => "my_secgroup", :description => "my sec group desc"} + @secgroup = Fog::Network[:openstack].security_groups.create(attributes) + @secgroup.wait_for { ready? } unless Fog.mocking? + !@secgroup.id.nil? + end + + tests('#destroy').succeeds do + @secgroup.destroy + end + end +end diff --git a/tests/openstack/models/network/security_groups_tests.rb b/tests/openstack/models/network/security_groups_tests.rb new file mode 100644 index 0000000000..0e12a06bb8 --- /dev/null +++ b/tests/openstack/models/network/security_groups_tests.rb @@ -0,0 +1,16 @@ +Shindo.tests('Fog::Network[:openstack] | security_groups collection', ['openstack']) do + + attributes = {:name => "my_secgroup", :description => "my sec group desc"} + collection_tests(Fog::Network[:openstack].security_groups, attributes, true) + + tests('success') do + attributes = {:name => "fogsecgroup", :description => "fog sec group desc"} + @secgroup = Fog::Network[:openstack].security_groups.create(attributes) + + tests('#all(filter)').succeeds do + secgroup = Fog::Network[:openstack].security_groups.all({:name => "fogsecgroup"}) + secgroup.first.name == "fogsecgroup" + end + @secgroup.destroy + end +end diff --git a/tests/openstack/requests/network/security_group_rule_tests.rb b/tests/openstack/requests/network/security_group_rule_tests.rb new file mode 100644 index 0000000000..def75f8cf6 --- /dev/null +++ b/tests/openstack/requests/network/security_group_rule_tests.rb @@ -0,0 +1,58 @@ +Shindo.tests('Fog::Network[:openstack] | security_grouprule requests', ['openstack']) do + + @security_group_rule_format = { + "id" => String, + "remote_group_id" => Fog::Nullable::String, + "direction" => String, + "remote_ip_prefix" => Fog::Nullable::String, + "protocol" => Fog::Nullable::String, + "ethertype" => String, + "port_range_max" => Fog::Nullable::Integer, + "port_range_min" => Fog::Nullable::Integer, + "security_group_id" => String, + "tenant_id" => String + } + + tests('success') do + attributes = {:name => "my_security_group", :description => "tests group"} + data = Fog::Network[:openstack].create_security_group(attributes).body["security_group"] + @sec_group_id = data["id"] + @sec_group_rule_id = nil + + tests("#create_security_group_rule(#{@sec_group_id}, 'ingress', attributes)").formats(@security_group_rule_format) do + attributes = { + :remote_ip_prefix => "0.0.0.0/0", + :protocol => "tcp", + :port_range_min => 22, + :port_range_max => 22 + } + data = Fog::Network[:openstack].create_security_group_rule(@sec_group_id, 'ingress', attributes).body["security_group_rule"] + @sec_group_rule_id = data["id"] + data + end + + tests("#get_security_group_rule('#{@sec_group_rule_id}')").formats(@security_group_rule_format) do + Fog::Network[:openstack].get_security_group_rule(@sec_group_rule_id).body["security_group_rule"] + end + + tests("#list_security_group_rules").formats("security_group_rules" => [@security_group_rule_format]) do + Fog::Network[:openstack].list_security_group_rules.body + end + + tests("#delete_security_group_rule('#{@sec_group_rule_id}')").succeeds do + Fog::Network[:openstack].delete_security_group_rule(@sec_group_rule_id) + end + + end + + tests('failure') do + tests('#get_security_group_rule(0)').raises(Fog::Network::OpenStack::NotFound) do + Fog::Network[:openstack].get_security_group_rule(0) + end + + tests('#delete_security_group_rule(0)').raises(Fog::Network::OpenStack::NotFound) do + Fog::Network[:openstack].delete_security_group_rule(0) + end + end + Fog::Network[:openstack].delete_security_group(@sec_group_id) +end diff --git a/tests/openstack/requests/network/security_group_tests.rb b/tests/openstack/requests/network/security_group_tests.rb new file mode 100644 index 0000000000..07c06960d6 --- /dev/null +++ b/tests/openstack/requests/network/security_group_tests.rb @@ -0,0 +1,43 @@ +Shindo.tests('Fog::Network[:openstack] | security_group requests', ['openstack']) do + + @security_group_format = { + "id" => String, + "name" => String, + "description" => String, + "tenant_id" => String, + "security_group_rules" => [Hash] + } + + tests('success') do + @sec_group_id = nil + + tests("#create_security_group('fog_security_group', 'tests group')").formats(@security_group_format) do + attributes = {:name => "fog_security_group", :description => "tests group"} + data = Fog::Network[:openstack].create_security_group(attributes).body["security_group"] + @sec_group_id = data["id"] + data + end + + tests("#get_security_group('#{@sec_group_id}')").formats(@security_group_format) do + Fog::Network[:openstack].get_security_group(@sec_group_id).body["security_group"] + end + + tests("#list_security_groups").formats('security_groups' => [@security_group_format]) do + Fog::Network[:openstack].list_security_groups.body + end + + tests("#delete_security_group('#{@sec_group_id}')").succeeds do + Fog::Network[:openstack].delete_security_group(@sec_group_id) + end + end + + tests('failure') do + tests("#get_security_group(0)").raises(Fog::Network::OpenStack::NotFound) do + Fog::Network[:openstack].get_security_group(0) + end + + tests("#delete_security_group(0)").raises(Fog::Network::OpenStack::NotFound) do + Fog::Network[:openstack].delete_security_group(0) + end + end +end diff --git a/tests/openstack/requests/orchestration/stack_tests.rb b/tests/openstack/requests/orchestration/stack_tests.rb index 73535c7f58..ded94e935d 100644 --- a/tests/openstack/requests/orchestration/stack_tests.rb +++ b/tests/openstack/requests/orchestration/stack_tests.rb @@ -15,21 +15,53 @@ 'links' => Array, } + @stack_details_format = @stack_format.merge ({ + 'parameters' => Fog::Nullable::Hash, + 'output' => Array, + 'disable_rollback' => Fog::Nullable::Boolean + }) + + @resource_format = { + 'links' => Array, + 'resource_name' => String, + 'resource_type' => String, + 'physical_resource_id' => String, + 'logical_resource_id' => String, + 'resource_status' => String, + 'resource_status_reason' => String, + 'updated_time' => Time, + 'required_by' => Array, + } + tests('success') do - tests('#create_stack("teststack")').formats(@create_format) do - Fog::Orchestration[:openstack].create_stack("teststack").body + stack_name = "teststack" + stack = nil + tests("#create_stack(#{stack_name})").formats(@create_format) do + stack = Fog::Orchestration[:openstack].create_stack(stack_name).body end tests('#list_stacks').formats({'stacks' => [@stack_format]}) do Fog::Orchestration[:openstack].list_stacks.body end - tests('#update_stack("teststack")').formats({}) do - Fog::Orchestration[:openstack].update_stack("teststack").body + tests("#update_stack(#{stack_name})").formats({}) do + Fog::Orchestration[:openstack].update_stack(stack_name).body + end + + tests("#delete_stack(#{stack_name}, #{stack['id']})").formats({}) do + Fog::Orchestration[:openstack].delete_stack(stack_name, stack["id"]).body + end + + tests("#describe_stack(#{stack_name}, #{stack['id']})").formats({'stack' => @stack_details_format}) do + Fog::Orchestration[:openstack].describe_stack(stack_name, stack["id"]).body + end + + tests("#list_stack_resources(#{stack_name}, #{stack['id']})").formats({'resources' => [@resource_format]}) do + Fog::Orchestration[:openstack].list_stack_resources(stack_name, stack["id"]).body end - tests('#delete_stack("teststack", "id")').formats({}) do - Fog::Orchestration[:openstack].delete_stack("teststack", "id").body + tests("#get_template(#{stack_name}, #{stack['id']})").formats({}) do + Fog::Orchestration[:openstack].get_template(stack_name, stack["id"]).body end end end