Return-Path: X-Original-To: apmail-incubator-deltacloud-dev-archive@minotaur.apache.org Delivered-To: apmail-incubator-deltacloud-dev-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E158E6297 for ; Mon, 16 May 2011 10:30:58 +0000 (UTC) Received: (qmail 30485 invoked by uid 500); 16 May 2011 10:30:58 -0000 Delivered-To: apmail-incubator-deltacloud-dev-archive@incubator.apache.org Received: (qmail 30440 invoked by uid 500); 16 May 2011 10:30:58 -0000 Mailing-List: contact deltacloud-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: deltacloud-dev@incubator.apache.org Delivered-To: mailing list deltacloud-dev@incubator.apache.org Received: (qmail 30431 invoked by uid 99); 16 May 2011 10:30:57 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 16 May 2011 10:30:57 +0000 X-ASF-Spam-Status: No, hits=-5.0 required=5.0 tests=RCVD_IN_DNSWL_HI,SPF_HELO_PASS,SPF_PASS,T_FRT_BELOW2 X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of mfojtik@redhat.com designates 209.132.183.28 as permitted sender) Received: from [209.132.183.28] (HELO mx1.redhat.com) (209.132.183.28) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 16 May 2011 10:30:53 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p4GAUXep024582 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 16 May 2011 06:30:33 -0400 Received: from dhcp-2-222.brq.redhat.com (dhcp-2-222.brq.redhat.com [10.34.2.222]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p4GAUTV4001624 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO); Mon, 16 May 2011 06:30:31 -0400 Subject: Re: [PATCH] implements 'firewalls' - which are ec2 security groups Mime-Version: 1.0 (Apple Message framework v1084) Content-Type: text/plain; charset=us-ascii From: Michal Fojtik In-Reply-To: <1305529563-8021-2-git-send-email-marios@redhat.com> Date: Mon, 16 May 2011 12:30:59 +0200 Content-Transfer-Encoding: quoted-printable Message-Id: <39B21952-2C35-415B-8FCB-838E34962F2C@redhat.com> References: <1305529563-8021-1-git-send-email-marios@redhat.com> <1305529563-8021-2-git-send-email-marios@redhat.com> To: deltacloud-dev@incubator.apache.org X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 On May 16, 2011, at 9:06 AM, marios@redhat.com wrote: Actually NACK. However this patch works fine the only major doubt I have on it are missing 'safely..end' block. This prevent reporting errors to client correctly. It would be also nice to have firewalls collection in Mock driver if = it's possible to run some tests on it, eventually add this stuff to EC2 = Cucumber features (I can help you with this). -- Michal > From: marios >=20 >=20 > Signed-off-by: marios > --- > server/deltacloud.rb | 2 + > server/lib/deltacloud/base_driver/base_driver.rb | 6 +- > server/lib/deltacloud/base_driver/features.rb | 8 +- > server/lib/deltacloud/drivers/ec2/ec2_driver.rb | 142 = +++++++++++++++++++++- > server/lib/deltacloud/models/firewall.rb | 22 ++++ > server/lib/deltacloud/models/firewall_rule.rb | 23 ++++ > server/server.rb | 105 = ++++++++++++++++ > server/views/firewalls/index.html.haml | 25 ++++ > server/views/firewalls/index.xml.haml | 23 ++++ > server/views/firewalls/new.html.haml | 11 ++ > server/views/firewalls/show.html.haml | 41 ++++++ > server/views/firewalls/show.xml.haml | 21 +++ > 12 files changed, 421 insertions(+), 8 deletions(-) > create mode 100644 server/lib/deltacloud/models/firewall.rb > create mode 100644 server/lib/deltacloud/models/firewall_rule.rb > create mode 100644 server/views/firewalls/index.html.haml > create mode 100644 server/views/firewalls/index.xml.haml > create mode 100644 server/views/firewalls/new.html.haml > create mode 100644 server/views/firewalls/show.html.haml > create mode 100644 server/views/firewalls/show.xml.haml >=20 > diff --git a/server/deltacloud.rb b/server/deltacloud.rb > index 7caf34f..5628e31 100644 > --- a/server/deltacloud.rb > +++ b/server/deltacloud.rb > @@ -36,6 +36,8 @@ require 'deltacloud/models/storage_volume' > require 'deltacloud/models/bucket' > require 'deltacloud/models/blob' > require 'deltacloud/models/load_balancer' > +require 'deltacloud/models/firewall' > +require 'deltacloud/models/firewall_rule' >=20 > require 'deltacloud/validation' > require 'deltacloud/helpers' > diff --git a/server/lib/deltacloud/base_driver/base_driver.rb = b/server/lib/deltacloud/base_driver/base_driver.rb > index d9ebd92..06363d9 100644 > --- a/server/lib/deltacloud/base_driver/base_driver.rb > +++ b/server/lib/deltacloud/base_driver/base_driver.rb > @@ -183,8 +183,12 @@ module Deltacloud > keys(credentials, opts).first if has_capability?(:keys) > end >=20 > + def firewall(credentials, opts=3D{}) > + firewalls(credentials, opts).first if = has_capability?(:firewalls) > + end > + > MEMBER_SHOW_METHODS =3D > - [ :realm, :image, :instance, :storage_volume, :bucket, :blob, = :key ] > + [ :realm, :image, :instance, :storage_volume, :bucket, :blob, = :key, :firewall ] >=20 > def has_capability?(capability) > if MEMBER_SHOW_METHODS.include?(capability.to_sym) > diff --git a/server/lib/deltacloud/base_driver/features.rb = b/server/lib/deltacloud/base_driver/features.rb > index 65c4cba..cb25a3b 100644 > --- a/server/lib/deltacloud/base_driver/features.rb > +++ b/server/lib/deltacloud/base_driver/features.rb > @@ -183,11 +183,11 @@ module Deltacloud > end > end >=20 > - declare_feature :instances, :security_group do > - description "Put instance in one or more security groups on = launch" > + declare_feature :instances, :firewall do > + description "Put instance in one or more firewalls (security = groups) on launch" > operation :create do > - param :security_group, :array, :optional, nil, > - "Array of security group names" > + param :firewalls, :array, :optional, nil, > + "Array of firewall (security group) id" > end > end >=20 > diff --git a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb = b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb > index 14c5829..4ef6efd 100644 > --- a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb > +++ b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb > @@ -16,6 +16,7 @@ >=20 > require 'deltacloud/base_driver' > require 'aws' > +require 'base64' >=20 > class Instance > attr_accessor :keyname > @@ -33,12 +34,13 @@ module Deltacloud > class EC2Driver < Deltacloud::BaseDriver >=20 > def supported_collections > - DEFAULT_COLLECTIONS + [ :keys, :buckets, :load_balancers, = :addresses ] > + > + DEFAULT_COLLECTIONS + [ :keys, :buckets, :load_balancers, = :addresses, :firewalls ] > end >=20 > feature :instances, :user_data > feature :instances, :authentication_key > - feature :instances, :security_group > + feature :instances, :firewall > feature :instances, :instance_count > feature :images, :owner_id > feature :buckets, :bucket_location > @@ -201,7 +203,7 @@ module Deltacloud > instance_options.merge!(:key_name =3D> opts[:keyname]) if = opts[:keyname] > instance_options.merge!(:availability_zone =3D> = opts[:realm_id]) if opts[:realm_id] > instance_options.merge!(:instance_type =3D> opts[:hwp_id]) = if opts[:hwp_id] && opts[:hwp_id].length > 0 > - instance_options.merge!(:group_ids =3D> = opts[:security_group]) if opts[:security_group] > + instance_options.merge!(:group_ids =3D> opts[:firewall]) if = opts[:firewall] > instance_options.merge!( > :min_count =3D> opts[:instance_count], > :max_count =3D> opts[:instance_count] > @@ -516,6 +518,7 @@ module Deltacloud > end > end >=20 > + > def addresses(credentials, opts=3D{}) > ec2 =3D new_client(credentials) > address_id =3D (opts and opts[:id]) ? [opts[:id]] : [] > @@ -571,6 +574,63 @@ module Deltacloud > end > end >=20 > +#-- > +#FIREWALLS - ec2 security groups > +#-- > + def firewalls(credentials, opts=3D{}) ^^ looks like a formatting typo.=20 > + ec2 =3D new_client(credentials) > + the_firewalls =3D [] > + groups =3D [] > + if opts[:id] > + groups =3D ec2.describe_security_groups([opts[:id]]) > + else > + groups =3D ec2.describe_security_groups() > + end > + groups.each do |security_group| > + the_firewalls <<=20 > + end Could be replaced by: the_firewalls =3D groups.collect { |security_group| = convert_security_group(security_group) } ** Also 'safely..end' blocks are missing here and on other places bellow = **. > + filter_on(the_firewalls, :id, opts) > + end > + > +#-- > +#Create firewall > +#-- > + def create_firewall(credentials, opts=3D{}) > + ec2 =3D new_client(credentials) > + ec2.create_security_group(opts["name"], = opts["description"]) > + Firewall.new( { :id=3D>opts["name"], :name=3D>opts["name"], > + :description =3D> opts["description"], = :owner_id =3D> "", :rules =3D> [] } ) > + end > + > +#-- > +#Delete firewall > +#-- > + def delete_firewall(credentials, opts=3D{}) > + ec2 =3D new_client(credentials) > + ec2.delete_security_group(opts["id"]) > + end > +#-- > +#Create firewall rule > +#-- > + def create_firewall_rule(credentials, opts=3D{}) > + ec2 =3D new_client(credentials) > + groups =3D [] > + opts['groups'].each do |k,v| > + groups << {"group_name" =3D> k, "owner" =3D>v} > + end > + ec2.manage_security_group_ingress(opts['firewall'], = opts['from_port'], opts['to_port'], opts['protocol'], > + "authorize", opts['addresses'], groups) > + end > +#-- > +#Delete firewall rule > +#-- > + def delete_firewall_rule(credentials, opts=3D{}) > + ec2 =3D new_client(credentials) > + firewall =3D opts[:firewall] > + protocol, from_port, to_port, addresses, groups =3D = firewall_rule_params(opts[:rule_id]) > + ec2.manage_security_group_ingress(firewall, from_port, = to_port, protocol, "revoke", addresses, groups) > + end > + > def valid_credentials?(credentials) > retval =3D true > begin > @@ -764,6 +824,82 @@ module Deltacloud > balancer > end >=20 > + #generate uid from firewall rule parameters (amazon doesn't = do this for us > + def firewall_rule_id(user_id, protocol, from_port, to_port, = sources) > + sources_string =3D "" > + sources.each do |source| > + source.each_pair do |key,value| > + sources_string<< "#{key}=3D#{value}&" > + end > + sources_string.chomp!("&") > + sources_string<<"|" > + end > + sources_string.chomp!("|") > + = #"type=3Dgroup&owner=3D123456789012&name=3Dnew_firewall|type=3Daddress&fam= ily=3Dipv4&address=3D192.168.1.1&prefix=3D24" > + id_string =3D "user #{user_id}:::protocol = #{protocol}:::from_port #{from_port}:::to_port #{to_port}:::sources = #{sources_string}" > + Base64.encode64(id_string) > + end > + > + #extract params from uid > + def firewall_rule_params(id) > + param_string =3D Base64.decode64(id) > + # = "#{user_id}:::#{protocol}:::#{from_port}:::#{to_port}:::#{sources_string}"= > + params =3D param_string.split(":::") > + protocol =3D params.grep(/protocol/).first.split(" ").last > + from_port =3D params.grep(/from_port/).first.split(" = ").last > + to_port =3D params.grep(/to_port/).first.split(" ").last > + sources =3D params.grep(/sources/).first.split(" ").last > + addresses =3D [] > + groups =3D [] > + sources.split("|").each do |source| > + current =3D source.split("&") > + type =3D current.grep(/type/).first.split("=3D").last > + case type > + when 'group' > + #type=3Dgroup&owner=3D123456789012&name=3Ddefault > + name =3D current.grep(/name/).first.split("=3D").last > + owner =3D current.grep(/owner/).first.split("=3D").last= > + groups << {'group_name' =3D> name, 'owner' =3D> = owner} > + when 'address' > + #type=3Daddress&family=3Dipv4&address=3D10.1.1.1&prefix= =3D24 > + address =3D = current.grep(/address/).last.split("=3D").last > + = address<<"/#{current.grep(/prefix/).first.split("=3D").last}" > + addresses << address > + end > + end > + return protocol, from_port, to_port, addresses, groups > + end > + > + #Convert ec2 security group to = server/lib/deltacloud/models/firewall > + def convert_security_group(security_group) > + rules =3D [] > + security_group[:aws_perms].each do |perm| > + sources =3D [] > + perm[:groups].each do |group| > + sources << {:type =3D> "group", :name =3D> = group[:group_name], :owner =3D> group[:owner]} > + end > + perm[:ip_ranges].each do |ip| > + sources << {:type =3D> "address", :family=3D>"ipv4", > + :address=3D>ip[:cidr_ip].split("/").first, > + :prefix=3D>ip[:cidr_ip].split("/").last} > + end > + rule_id =3D firewall_rule_id(security_group[:aws_owner], = perm[:protocol], > + perm[:from_port] , = perm[:to_port], sources) > + rules << Firewall_Rule.new({:id =3D> rule_id, Please use 'camel case' for class names in Ruby. Ruby recommends UpperCamelCase for class names (e.g. UserProfile), = lowercase words separated by underscores for variables (e.g. = last_variable_used) and uppercase words separated by underscores for = constants (e.g. WIKI_VERSION). > + :allow_protocol =3D> = perm[:protocol], > + :port_from =3D> = perm[:from_port], > + :port_to =3D> perm[:to_port], > + :direction =3D> 'ingress', > + :sources =3D> sources}) > + end > + Firewall.new( { :id =3D> security_group[:aws_group_name], > + :name =3D> = security_group[:aws_group_name], > + :description =3D> = security_group[:aws_description], > + :owner_id =3D> = security_group[:aws_owner], > + :rules =3D> rules > + } ) There is no need to use '{}' brackets in initializer, when there is only = one Hash argument. > + end > + > def convert_state(ec2_state) > case ec2_state > when "terminated" > diff --git a/server/lib/deltacloud/models/firewall.rb = b/server/lib/deltacloud/models/firewall.rb > new file mode 100644 > index 0000000..dc0ae3d > --- /dev/null > +++ b/server/lib/deltacloud/models/firewall.rb > @@ -0,0 +1,22 @@ > +# > +# Licensed to the Apache Software Foundation (ASF) under one or more > +# contributor license agreements. See the NOTICE file distributed = with > +# this work for additional information regarding copyright ownership. = The > +# ASF licenses this file to you under the Apache License, Version 2.0 = (the > +# "License"); you may not use this file except in compliance with the > +# License. You may obtain a copy of the License at > +# > +# http://www.apache.org/licenses/LICENSE-2.0 > +# > +# Unless required by applicable law or agreed to in writing, software > +# distributed under the License is distributed on an "AS IS" BASIS, = WITHOUT > +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. = See the > +# License for the specific language governing permissions and = limitations > +# under the License. > + > +class Firewall < BaseModel > + attr_accessor :name > + attr_accessor :description > + attr_accessor :owner_id > + attr_accessor :rules > +end > \ No newline at end of file > diff --git a/server/lib/deltacloud/models/firewall_rule.rb = b/server/lib/deltacloud/models/firewall_rule.rb > new file mode 100644 > index 0000000..df353a5 > --- /dev/null > +++ b/server/lib/deltacloud/models/firewall_rule.rb > @@ -0,0 +1,23 @@ > +# > +# Licensed to the Apache Software Foundation (ASF) under one or more > +# contributor license agreements. See the NOTICE file distributed = with > +# this work for additional information regarding copyright ownership. = The > +# ASF licenses this file to you under the Apache License, Version 2.0 = (the > +# "License"); you may not use this file except in compliance with the > +# License. You may obtain a copy of the License at > +# > +# http://www.apache.org/licenses/LICENSE-2.0 > +# > +# Unless required by applicable law or agreed to in writing, software > +# distributed under the License is distributed on an "AS IS" BASIS, = WITHOUT > +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. = See the > +# License for the specific language governing permissions and = limitations > +# under the License. > + > +class Firewall_Rule < BaseModel > + attr_accessor :allow_protocol # tcp/udp/icmp > + attr_accessor :port_from > + attr_accessor :port_to > + attr_accessor :sources > + attr_accessor :direction #ingress egress > +end > diff --git a/server/server.rb b/server/server.rb > index 4da8357..a318df6 100644 > --- a/server/server.rb > +++ b/server/server.rb > @@ -843,6 +843,7 @@ collection :buckets do >=20 > end >=20 > + > get '/api/addresses/:id/associate' do > @instances =3D driver.instances(credentials) > @address =3D Address::new(:id =3D> params[:id]) > @@ -929,3 +930,107 @@ collection :addresses do > end >=20 > end > + > +#html for creating a new firewall > +get '/api/firewalls/new' do > + respond_to do |format| > + format.html { haml :"firewalls/new" } > + end > +end > + > +#html for creating a new firewall rule > +get '/api/firewalls/:firewall/new_rule' do > + @firewall_name =3D params[:firewall] > + respond_to do |format| > + format.html {haml :"firewalls/new_rule" } > + end > +end > + > +#create new firewall rule > +post '/api/firewalls/:firewall/rules' do > + opts =3D {} > + opts['firewall'] =3D params[:firewall] # must specify group_name or = group_id > + opts['protocol'] =3D params[:protocol] > + opts['from_port'] =3D params[:from_port] > + opts['to_port'] =3D params[:to_port] > + addresses =3D params.inject([]){|result,current| result << = current.last unless current.grep(/^ip[-_]address/i).empty?; result} > + groups =3D {} > + max_groups =3D params.select{|k,v| k=3D~/^group/}.size/2 > + for i in (1..max_groups) do > + groups.merge!({params["group#{i}"]=3D>params["group#{i}owner"]}) > + end > + opts['addresses'] =3D addresses > + opts['groups'] =3D groups > + driver.create_firewall_rule(credentials, opts) > + @firewall =3D driver.firewall(credentials, {:id =3D> = params[:firewall]}) > + respond_to do |format| > + format.html {haml :"firewalls/show"} > + format.xml do > + response.status =3D 201 #created > + haml :"firewalls/show" > + end > + end > +end This should be moved to 'collection' block, defined like: operation :rules, :method =3D> :post, :member =3D> true description "Blabla" param :firewall, :required, :string param :protocol, :required, :string param :from_port, :required, :string param :to_port, :required, :string with_capability :create_firewall_rule control do { ... } end Benefit of using this operation block inside collection is parameter validation, error handling and auto documentation. We should try to use Rabbit everywhere where it's possible. > + > +#delete a firewall rule > +delete '/api/firewalls/:firewall/:rule' do > + opts =3D {} > + opts[:firewall] =3D params[:firewall] > + opts[:rule_id] =3D params[:rule] > + driver.delete_firewall_rule(credentials, opts) > + respond_to do |format| > + format.html {redirect firewall_url(params[:firewall])} > + format.xml {204} > + format.json {204} > + end > +end operation :rule, :method =3D> :delete, :member =3D> true description "Blabla" param :id, :string, :required param :rule_id, :string, :required with_capability :delete_firewall_rule control do { ... } end -> This will generate URI: DELETE /api/firewalls/123/rules I suggest to use parameter 'rule_id' to identify rule used for deletion. > +collection :firewalls do > + description "Allow user to define firewall rules for an instance = (ec2 security groups) eg expose ssh access [port 22, tcp]." > + > + operation :index do > + description 'List all firewalls' > + with_capability :firewalls > + control { filter_all(:firewalls) } > + end > + > + operation :show do > + description 'Show details for a specific firewall - list all = rules' > + with_capability :firewall > + param :id, :string, :required > + control { show(:firewall) } > + end > + > + operation :create do > + description 'Create a new firewall' > + with_capability :create_firewall > + param :name, :string, :required > + param :description, :string, :required > + control do > + @firewall =3D driver.create_firewall(credentials, params ) > + respond_to do |format| > + format.xml do > + response.status =3D 201 # Created > + haml :"firewalls/show" > + end > + format.html {haml :"firewalls/show"} > + end > + end > + end > + > + operation :destroy do > + description 'Delete a specified firewall - error if firewall has = rules' > + with_capability :delete_firewall > + param :id, :string, :required > + control do > + driver.delete_firewall(credentials, params) > + respond_to do |format| > + format.xml { 204 } > + format.json { 204 } > + format.html { redirect(firewalls_url) } > + end > + end > + end > + > +end #firewalls > diff --git a/server/views/firewalls/index.html.haml = b/server/views/firewalls/index.html.haml > new file mode 100644 > index 0000000..3312a32 > --- /dev/null > +++ b/server/views/firewalls/index.html.haml > @@ -0,0 +1,25 @@ > +%h1 Firewalls > +%br > +%p > + =3Dlink_to 'Create new firewall', "/api/firewalls/new" > +%table.display > + %thead > + %tr > + %th Id > + %th Name > + %th Description > + %th Owner ID > + %th Rules > + %tbody > + - @firewalls.each do |firewall| > + %tr > + %td > + =3D link_to firewall.id, firewall_url(firewall.id) > + %td > + =3D firewall.name > + %td > + =3D firewall.description > + %td > + =3D firewall.owner_id > + %td > + =3D link_to 'view rules', firewall_url(firewall.id) > diff --git a/server/views/firewalls/index.xml.haml = b/server/views/firewalls/index.xml.haml > new file mode 100644 > index 0000000..8397f2d > --- /dev/null > +++ b/server/views/firewalls/index.xml.haml > @@ -0,0 +1,23 @@ > +!!! XML > +%firewalls > + - @firewalls.each do |firewall| > + %firewall{:href =3D> firewall_url(firewall.id), :id =3D> = firewall.id} > + - firewall.attributes.select{ |attr| attr !=3D :id && attr!=3D = :rules}.each do |attribute| > + - haml_tag("#{attribute}".tr('-', '_'), :<) do > + - if [:name, :description].include?(attribute) > + =3Dcdata do > + - haml_concat firewall.send(attribute) > + - else > + - haml_concat firewall.send(attribute) > + %rules > + - firewall.rules.each do |rule| > + %rule > + - rule.attributes.select{|attr| attr !=3D :sources}.each = do |rule_attrib| > + - haml_tag("#{rule_attrib}".tr('-', '_'), :<) do > + - haml_concat rule.send(rule_attrib) > + %sources > + - rule.sources.each do |source| > + - if source[:type] =3D=3D "group" > + %source{:name =3D> source[:name], :type=3D> = source[:type], :owner=3D> source[:owner]} > + - else > + %source{:prefix =3D> source[:prefix], :address=3D> = source[:address], :family=3D>source[:family], :type =3D> source[:type]} > \ No newline at end of file > diff --git a/server/views/firewalls/new.html.haml = b/server/views/firewalls/new.html.haml > new file mode 100644 > index 0000000..4a230a6 > --- /dev/null > +++ b/server/views/firewalls/new.html.haml > @@ -0,0 +1,11 @@ > +%h1 New Firewall > + > +%form{:action =3D> firewalls_url, :method =3D> :post} > + %label > + Firewall Name > + %input{:name =3D> 'name', :size =3D> 25}/ > + %br > + %label > + Firewall Description > + %input{:name =3D> 'description', :size =3D> 100}/ > + %input{:type =3D> :submit, :name =3D> "commit", :value=3D>"create"} > \ No newline at end of file > diff --git a/server/views/firewalls/show.html.haml = b/server/views/firewalls/show.html.haml > new file mode 100644 > index 0000000..e6a186f > --- /dev/null > +++ b/server/views/firewalls/show.html.haml > @@ -0,0 +1,41 @@ > +%h1 Firewall > +%h2 > + =3D @firewall.id > +%dl > + %di > + %dt Name > + %dd > + =3D @firewall.name > + %dt Owner > + %dd > + =3D @firewall.owner_id > + %dt Description > + %dd > + =3D @firewall.description > + > +%h2 > + Rules > + %br > + %p > + =3Dlink_to 'Create a new rule', = "/api/firewalls/#{@firewall.name}/new_rule" > +%dl > + - @firewall.rules.each do |rule| > + %di > + Rule > + - rule.attributes.select{|attr| attr !=3D :sources}.each do = |attrib| > + %dt #{attrib} > + %dd > + =3D rule.send(attrib) > + %dt sources > + %dd > + - rule.sources.each do |source| > + - if source[:type] =3D=3D "group" > + type: #{source[:type]}, name: #{source[:name]}, owner: = #{source[:owner]} > + %br > + - else > + type: #{source[:type]}, family: #{source[:family]}, = address: #{source[:address]}, prefix: #{source[:prefix]} > + %br > + %dd > + =3D link_to_action 'Delete Rule', = destroy_firewall_url(@firewall.name) + "/#{rule.id}", :delete > + %dd > + =3D link_to_action 'Delete Firewall', = destroy_firewall_url(@firewall.name), :delete > \ No newline at end of file > diff --git a/server/views/firewalls/show.xml.haml = b/server/views/firewalls/show.xml.haml > new file mode 100644 > index 0000000..200d2cd > --- /dev/null > +++ b/server/views/firewalls/show.xml.haml > @@ -0,0 +1,21 @@ > +!!! XML > +%firewall{:href =3D> firewall_url(@firewall.id), :id =3D> = @firewall.id} > + - @firewall.attributes.select{ |attr| attr !=3D :id && attr!=3D = :rules}.each do |attribute| > + - haml_tag("#{attribute}".tr('-', '_'), :<) do > + - if [:name, :description].include?(attribute) > + =3Dcdata do > + - haml_concat @firewall.send(attribute) > + - else > + - haml_concat @firewall.send(attribute) > + %rules > + - @firewall.rules.each do |rule| > + %rule > + - rule.attributes.select{|attr| attr !=3D :sources}.each do = |rule_attrib| > + - haml_tag("#{rule_attrib}".tr('-', '_'), :<) do > + - haml_concat rule.send(rule_attrib) > + %sources > + - rule.sources.each do |source| > + - if source[:type] =3D=3D "group" > + %source{:name =3D> source[:name], :type=3D> = source[:type], :owner=3D>source[:owner]} > + - else > + %source{:prefix =3D> source[:prefix], :address=3D> = source[:address], :family=3D>source[:family], :type =3D> source[:type]} > \ No newline at end of file > --=20 > 1.7.3.4 >=20 ------------------------------------------------------ Michal Fojtik, mfojtik@redhat.com Deltacloud API: http://deltacloud.org