kakine 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 70641f4e229c0b370d35779df007a7df6da8652f
4
- data.tar.gz: 2dde1b80581774ea0c74f8848e4f703e25faf22f
3
+ metadata.gz: 08d689b653e85c4346a1ef9dc194dab3e247e279
4
+ data.tar.gz: 235a610f938c16abff1e046340a8361f6cbd9e27
5
5
  SHA512:
6
- metadata.gz: 4cead3fba0343c55d0af964843358cdcaaee3e6b0249a5e18195b8fc84cc266cab4930faa0c6cac8012ed111c32a36ac567fa3bc00a32f8fced787a74d6d92d1
7
- data.tar.gz: 08660d1645a78545d7bf22aff0f0dd074de1d0b358045428a559a1b604350e2f165812eb8351c17d9a63742c0e33bd009e87fc251a8d0f217e3c47c7e32fc85a
6
+ metadata.gz: 6a688afc029c91f62930b1c393cbf514bf0cc7290d3c1e2b5628780b9603f02aba816b196f735d79ef7fcf9ee7cd5d16c7cd915efcb789b2e1e9657b53759b60
7
+ data.tar.gz: 6166fdac44b9ed3c370f30681caa18c287fd2736558f96abcfe97c7a1748ed0926802e710d0528624b57bdcfd51f64b771615b2d6595f1df225fe41c76b74d62
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Kakine
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/hsbt/kakine.png)](https://travis-ci.org/hsbt/kakine)
3
+ [![Build Status](https://travis-ci.org/yaocloud/kakine.svg?branch=master)](https://travis-ci.org/yaocloud/kakine)
4
4
 
5
5
  Kakine(垣根) is configuration management tool of Security Group on OpenStack.
6
6
 
@@ -44,23 +44,22 @@ rails:
44
44
  remote_ip: 0.0.0.0/0
45
45
  ```
46
46
 
47
- You need to put fog configuration to home directory.
47
+ You need to put a configuration file to home directory.
48
48
 
49
49
  ```sh
50
- % cat ~/.fog
51
- default:
52
- openstack_auth_url: "http://your-openstack-endpoint/v2.0/tokens"
53
- openstack_username: "admin"
54
- openstack_tenant: "admin"
55
- openstack_api_key: "admin-no-password"
50
+ % cat ~/.kakine
51
+ auth_url: "http://your-openstack-endpoint/v2.0"
52
+ username: "admin"
53
+ tenant: "admin"
54
+ password: "admin"
56
55
  ```
57
56
 
58
57
  run following command.
59
58
 
60
59
  ```sh
61
60
  $ kakine show -t tenant_name # show Security Group of tenant_name
62
- $ kaname apply -t tenant_name --dryrun # You can see all of invoke commands(dryrun)
63
- $ kaname apply -t tenant_name # apply configuration into OpenStack
61
+ $ kakine apply -t tenant_name --dryrun # You can see all of invoke commands(dryrun)
62
+ $ kakine apply -t tenant_name # apply configuration into OpenStack
64
63
  ```
65
64
 
66
65
  You can create or change Security Group on targeting tenant.
@@ -68,7 +67,7 @@ You can create or change Security Group on targeting tenant.
68
67
  If you need to initialize your Security Gruop, you can get it via following command:
69
68
 
70
69
  ```sh
71
- $ kaname show -t tenant_name > tenant_name.yaml
70
+ $ kakine show -t tenant_name > tenant_name.yaml
72
71
  ```
73
72
 
74
73
  ## Development
@@ -19,9 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_dependency 'fog'
22
+ spec.add_dependency "yao", "~> 0.2.0"
23
23
  spec.add_dependency 'thor'
24
- spec.add_dependency 'hashdiff'
25
24
 
26
25
  spec.add_development_dependency "bundler"
27
26
  spec.add_development_dependency "rake"
@@ -1,12 +1,27 @@
1
+ require 'yaml'
2
+ require 'thor'
3
+ require 'json'
4
+ require 'yao'
1
5
  require "kakine/version"
6
+ require 'kakine/config'
2
7
  require 'kakine/cli'
3
- require 'kakine/operation'
8
+ require 'kakine/builder'
9
+ require 'kakine/option'
10
+ require 'kakine/director'
4
11
  require 'kakine/adapter'
12
+ require 'kakine/adapter/base'
13
+ require 'kakine/adapter/real'
14
+ require 'kakine/adapter/mock'
5
15
  require 'kakine/resource'
16
+ require 'kakine/resource/openstack'
17
+ require 'kakine/resource/yaml'
6
18
  require 'kakine/security_group'
7
19
  require 'kakine/security_rule'
8
- require 'kakine/validate'
9
20
 
10
21
  module Kakine
22
+ class Error < StandardError; end
23
+ class ConfigureError < Error; end
24
+ class SecurityRuleError < Error; end
11
25
  end
12
26
 
27
+ Kakine::Config.setup unless ENV['RACK_ENV'] == 'test'
@@ -1,22 +1,16 @@
1
- require 'kakine/adapter/real'
2
- require 'kakine/adapter/mock'
3
-
1
+ require 'singleton'
4
2
  module Kakine
5
3
  class Adapter
6
- def self.set_option(dryrun)
7
- @@dryrun = dryrun
8
- end
9
-
10
- def self.get_instance
11
- @@adapter ||= if @@dryrun
12
- Kakine::Adapter::Mock.new
13
- else
14
- Kakine::Adapter::Real.new
4
+ @@adapter = nil
5
+ include Singleton
6
+ class << self
7
+ def instance
8
+ @@adapter ||= if Kakine::Option.dryrun?
9
+ Kakine::Adapter::Mock.new
10
+ else
11
+ Kakine::Adapter::Real.new
12
+ end
15
13
  end
16
14
  end
17
-
18
- private
19
- def initialize
20
- end
21
15
  end
22
16
  end
@@ -0,0 +1,17 @@
1
+ module Kakine
2
+ class Adapter
3
+ module Base
4
+ def tenants
5
+ Yao::Tenant.list
6
+ end
7
+
8
+ def security_groups
9
+ Yao::SecurityGroup.list
10
+ end
11
+
12
+ def get_security_group(remote_group_id)
13
+ Yao::SecurityGroup.get(remote_group_id)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,6 +1,7 @@
1
1
  module Kakine
2
2
  class Adapter
3
3
  class Mock
4
+ include Kakine::Adapter::Base
4
5
  def create_rule(security_group_id, direction, security_rule)
5
6
  attributes = {}
6
7
  %w(protocol port_range_max port_range_min remote_ip ethertype).each do |k|
@@ -11,21 +12,32 @@ module Kakine
11
12
  end
12
13
 
13
14
  puts "Create Rule: #{security_group_id} - #{security_rule.direction}: #{attributes}"
15
+ "Create Rule: #{security_group_id}"
14
16
  end
15
17
 
16
18
  def delete_rule(security_group_rule_id)
17
19
  puts "Delete Rule: #{security_group_rule_id}"
20
+ "Delete Rule: #{security_group_rule_id}"
18
21
  end
19
22
 
20
23
  def create_security_group(attributes)
21
24
  data = {}
22
25
  attributes.each{|k,v| data[k.to_sym] = v}
23
26
  puts "Create Security Group: #{data}"
24
- "[Mock] #{attributes[:name]} ID"
27
+ "Create Security Group: #{attributes[:name]}"
25
28
  end
26
29
 
27
30
  def delete_security_group(security_group_id)
28
31
  puts "Delete Security Group: #{security_group_id}"
32
+ "Delete Security Group: #{security_group_id}"
33
+ end
34
+
35
+ def security_group(tenant_name, sg_name)
36
+ self
37
+ end
38
+
39
+ def id(sg_name)
40
+ "#{sg_name}"
29
41
  end
30
42
  end
31
43
  end
@@ -1,52 +1,65 @@
1
- require 'json'
2
1
  module Kakine
3
2
  class Adapter
4
3
  class Real
4
+ include Kakine::Adapter::Base
5
5
  def create_rule(security_group_id, direction, security_rule)
6
- attributes = {}
7
- %w(protocol port_range_max port_range_min remote_ip ethertype).each do |k|
8
- attributes[k] = eval("security_rule.#{k}")
9
- end
10
- if attributes["remote_ip"]
11
- attributes["remote_ip_prefix"] = attributes.delete("remote_ip")
12
- end
13
-
14
- data = {}
15
- attributes.each{|k,v| data[k.to_sym] = v}
16
6
  begin
17
- Fog::Network[:openstack].create_security_group_rule(security_group_id, direction, data)
18
- rescue Excon::Errors::Conflict => e
19
- JSON.parse(e.response[:body]).each { |e,m| puts "#{e}:#{m["message"]}" }
20
- rescue Excon::Errors::BadRequest => e
21
- JSON.parse(e.response[:body]).each { |e,m| puts "#{e}:#{m["message"]}" }
7
+ security_rule = symbolized_rule(security_rule)
8
+ Yao::SecurityGroupRule.create(security_rule.merge({'security_group_id' => security_group_id, 'direction' => direction}))
9
+ rescue Excon::Errors::Conflict, Excon::Errors::BadRequest => e
10
+ error_message(e.response[:body])
11
+ rescue Kakine::SecurityRuleError => e
12
+ puts e
22
13
  end
23
14
  end
24
15
 
25
16
  def delete_rule(security_group_rule_id)
26
- Fog::Network[:openstack].delete_security_group_rule(security_group_rule_id)
17
+ Yao::SecurityGroupRule.destroy(security_group_rule_id)
27
18
  end
28
19
 
29
20
  def create_security_group(attributes)
30
- data = {}
31
- attributes.each{|k,v| data[k.to_sym] = v}
32
21
  begin
33
- response = Fog::Network[:openstack].create_security_group(data)
34
- response.data[:body]["security_group"]["id"]
35
- rescue Excon::Errors::Conflict => e
36
- JSON.parse(e.response[:body]).each { |e,m| puts "#{e}:#{m["message"]}" }
37
- rescue Excon::Errors::BadRequest => e
38
- JSON.parse(e.response[:body]).each { |e,m| puts "#{e}:#{m["message"]}" }
22
+ security_group = Yao::SecurityGroup.create(symbolized_group(attributes))
23
+ {"id" => security_group.id}
24
+ rescue Excon::Errors::Conflict, Excon::Errors::BadRequest => e
25
+ error_message(e.response[:body])
39
26
  end
40
27
  end
41
28
 
42
29
  def delete_security_group(security_group_id)
43
30
  begin
44
- Fog::Network[:openstack].delete_security_group(security_group_id)
45
- rescue Excon::Errors::Conflict => e
46
- JSON.parse(e.response[:body]).each { |e,m| puts "#{e}:#{m["message"]}" }
47
- rescue Excon::Errors::BadRequest => e
48
- JSON.parse(e.response[:body]).each { |e,m| puts "#{e}:#{m["message"]}" }
31
+ Yao::SecurityGroup.destroy(security_group_id)
32
+ rescue Excon::Errors::Conflict, Excon::Errors::BadRequest => e
33
+ error_message(e.response[:body])
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def error_message(errors)
40
+ if errors.kind_of?(JSON)
41
+ JSON.parse(errors.response[:body]).each { |e,m| puts "#{e}:#{m["message"]}" }
42
+ else
43
+ puts errors
44
+ end
45
+ end
46
+
47
+ def symbolized_group(attributes)
48
+ attributes.inject({}){|data,(k,v)|data[k.to_sym] = v; data }
49
+ end
50
+
51
+ def symbolized_rule(security_rule)
52
+ attributes = {}
53
+ %w(protocol port_range_max port_range_min remote_ip ethertype).each do |k|
54
+ attributes[k.to_sym] = security_rule.send(k)
55
+ end
56
+
57
+ if security_rule.remote_group
58
+ attributes[:remote_group_id] = security_rule.remote_group_id
59
+ else
60
+ attributes[:remote_ip_prefix] = attributes.delete(:remote_ip) if attributes[:remote_ip]
49
61
  end
62
+ attributes
50
63
  end
51
64
  end
52
65
  end
@@ -0,0 +1,96 @@
1
+ module Kakine
2
+ class Builder
3
+ class << self
4
+ def create_security_group(sg)
5
+ attributes = { name: sg.name, description: sg.description, tenant_id: sg.tenant_id }
6
+ security_group_id = Kakine::Adapter.instance.create_security_group(attributes)
7
+ delete_default_security_rule(sg.tenant_name, sg.name)
8
+ security_group_id
9
+ end
10
+
11
+ def delete_security_group(sg)
12
+ Kakine::Adapter.instance.delete_security_group(sg.id)
13
+ end
14
+
15
+ def first_create_security_group(new_sg)
16
+ create_security_group(new_sg)
17
+ new_sg.rules.map do |rule|
18
+ create_security_rule(new_sg.tenant_name, new_sg.name, rule)
19
+ end if new_sg.has_rules?
20
+ end
21
+
22
+ def clean_up_security_group(new_sgs, current_sgs)
23
+ current_sgs.map do |current_sg|
24
+ delete_security_group(current_sg) if new_sgs.none? { |new_sg| current_sg.name == new_sg.name }
25
+ end
26
+ end
27
+
28
+ def convergence_security_group(new_sg, current_sg)
29
+ if new_sg.description != current_sg.description
30
+ delete_security_group(current_sg)
31
+ first_create_security_group(new_sg)
32
+ else
33
+ clean_up_security_rule(new_sg, current_sg)
34
+ first_create_rule(new_sg, current_sg)
35
+ end
36
+ end
37
+
38
+ def already_setup_security_group(new_sg, current_sgs)
39
+ current_sgs.find { |current_sg| current_sg.name == new_sg.name }
40
+ end
41
+
42
+ def create_security_rule(tenant_name, sg_name, rule)
43
+ sg = Kakine::Resource.get(:openstack).security_group(tenant_name, sg_name)
44
+ security_group_id = Kakine::Option.dryrun? && sg.nil? ? Kakine::Adapter.instance.id(sg_name) : sg.id
45
+ Kakine::Adapter.instance.create_rule(security_group_id, rule.direction, rule)
46
+ end
47
+
48
+ def delete_security_rule(tenant_name, sg_name, rule)
49
+ Kakine::Adapter.instance.delete_rule(rule.id)
50
+ end
51
+
52
+ def delete_default_security_rule(tenant_name, sg_name)
53
+ target_sg = Kakine::Resource.get(:openstack).load_security_group.find do |sg|
54
+ sg.name == sg_name
55
+ end
56
+
57
+ target_sg.rules.map do |rule|
58
+ delete_security_rule(tenant_name, sg_name, rule)
59
+ end if target_sg
60
+ end
61
+
62
+ def first_create_rule(new_sg, current_sg)
63
+ new_sg.rules.map do |rule|
64
+ unless current_sg.find_by_rule(rule)
65
+ create_security_rule(new_sg.tenant_name, new_sg.name, rule)
66
+ end
67
+ end
68
+ end
69
+
70
+ def clean_up_security_rule(new_sg, current_sg)
71
+ current_sg.rules.map do |rule|
72
+ delete_security_rule(new_sg.tenant_name, new_sg.name, rule) unless new_sg.find_by_rule(rule)
73
+ end
74
+ end
75
+
76
+ def security_groups
77
+ sgs = Kakine::Resource.get(:openstack).security_groups_hash
78
+ delete_id_column(sgs).to_yaml
79
+ end
80
+
81
+ def delete_id_column(sgs)
82
+ case sgs
83
+ when Array
84
+ sgs.map { |sg| delete_id_column(sg) }
85
+ when Hash
86
+ sgs.inject({}) do |hash, (k, v)|
87
+ hash[k] = delete_id_column(v) if k != "id"
88
+ hash
89
+ end
90
+ else
91
+ sgs
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -1,14 +1,13 @@
1
- require 'thor'
2
- require 'fog'
3
- require 'yaml'
4
- require 'hashdiff'
1
+ require 'kakine'
2
+
5
3
  module Kakine
6
4
  class CLI < Thor
7
5
 
8
6
  option :tenant, type: :string, aliases: '-t'
9
7
  desc 'show', 'show Security Groups specified tenant'
10
8
  def show
11
- puts Kakine::Resource.security_groups_hash(options[:tenant]).to_yaml
9
+ Kakine::Option.set_options(options)
10
+ Kakine::Director.show_current_security_group
12
11
  end
13
12
 
14
13
  option :tenant, type: :string, aliases: "-t"
@@ -16,24 +15,8 @@ module Kakine
16
15
  option :filename, type: :string, aliases: "-f"
17
16
  desc 'apply', "apply local configuration into OpenStack"
18
17
  def apply
19
- filename = options[:filename] ? options[:filename] : "#{options[:tenant]}.yaml"
20
- Kakine::Adapter.set_option(options[:dryrun])
21
-
22
- current_security_groups = Kakine::Resource.get_current(options[:tenant])
23
- new_security_groups = Kakine::Resource.load_security_group_by_yaml(filename, options[:tenant])
24
-
25
- return unless new_security_groups
26
- new_security_groups.each do |new_sg|
27
- registered_sg = current_security_groups.find { |cur_sg| cur_sg.name == new_sg.name }
28
- if registered_sg
29
- new_sg.convergence!(registered_sg) if new_sg != registered_sg
30
- else
31
- new_sg.register!
32
- end
33
- end
34
- current_security_groups.each do |current_sg|
35
- current_sg.unregister! if new_security_groups.none? { |new_sg| current_sg.name == new_sg.name }
36
- end
18
+ Kakine::Option.set_options(options)
19
+ Kakine::Director.apply
37
20
  end
38
21
  end
39
22
  end
@@ -0,0 +1,39 @@
1
+ require 'yao'
2
+ require 'yaml'
3
+
4
+ module Kakine
5
+ class Config
6
+ def self.setup
7
+ load_config
8
+ setup_yao
9
+ end
10
+
11
+ private
12
+
13
+ def self.load_config
14
+ config_file = File.join(Dir.home, '.kakine')
15
+ raise '~/.kakine is missing' unless File.exists?(config_file)
16
+
17
+ config = YAML.load_file(config_file)
18
+
19
+ %w[auth_url tenant username password].each do |conf_item|
20
+ raise "Configuration '#{conf_item}' is missing. Check your ~/.kakine" unless config[conf_item]
21
+ end
22
+
23
+ @@auth_url = config['auth_url']
24
+ @@tenant = config['tenant']
25
+ @@username = config['username']
26
+ @@password = config['password']
27
+ true
28
+ end
29
+
30
+ def self.setup_yao
31
+ Yao.configure do
32
+ auth_url @@auth_url
33
+ tenant_name @@tenant
34
+ username @@username
35
+ password @@password
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,26 @@
1
+ module Kakine
2
+ class Director
3
+ class << self
4
+ def show_current_security_group
5
+ puts Kakine::Builder.security_groups
6
+ end
7
+
8
+ def apply
9
+ current_sgs = Kakine::Resource.get(:openstack).load_security_group
10
+ new_sgs = Kakine::Resource.get(:yaml).load_security_group
11
+ new_sgs.each do |new_sg|
12
+ if already_sg = Kakine::Builder.already_setup_security_group(new_sg, current_sgs)
13
+ Kakine::Builder.convergence_security_group(new_sg, already_sg) if new_sg != already_sg
14
+ else
15
+ Kakine::Builder.first_create_security_group(new_sg)
16
+ end
17
+ end
18
+
19
+ Kakine::Builder.clean_up_security_group(new_sgs, current_sgs)
20
+
21
+ rescue Kakine::Error => e
22
+ puts "[error] #{e}"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ require 'singleton'
2
+ module Kakine
3
+ class Option
4
+ include Singleton
5
+ class << self
6
+ def set_options(options)
7
+ @@options = options
8
+ end
9
+
10
+ def yaml_name
11
+ @@options[:filename] ? @@options[:filename] : "#{@@options[:tenant]}.yaml"
12
+ end
13
+
14
+ def tenant_name
15
+ @@options["tenant"]
16
+ end
17
+
18
+ def dryrun?
19
+ @@options["dryrun"]
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,89 +1,12 @@
1
1
  module Kakine
2
2
  class Resource
3
3
  class << self
4
- def load_security_group_by_yaml(filename, tenant_name)
5
- load_yaml = yaml(filename)
6
- return false unless Kakine::Validate.validate_file_input(load_yaml)
7
- load_yaml.map { |sg| Kakine::SecurityGroup.new(tenant_name, sg) }
8
- end
9
-
10
- def get_current(tenant_name)
11
- Kakine::Resource.security_groups_hash(tenant_name).map do |sg|
12
- Kakine::SecurityGroup.new(tenant_name, sg)
13
- end
14
- end
15
-
16
- def yaml(filename)
17
- YAML.load_file(filename).to_hash
18
- end
19
-
20
- def tenant(tenant_name)
21
- @tenant ||= Fog::Identity[:openstack].tenants.detect{|t| t.name == tenant_name}
22
- end
23
-
24
- def security_group(tenant_name, security_group_name)
25
- security_groups_on_tenant(tenant_name).detect{|sg| sg.name == security_group_name}
26
- end
27
-
28
- def security_group_rule(security_group, attributes)
29
- security_group.security_group_rules.detect do |sg|
30
-
31
- sg.direction == attributes.direction &&
32
- sg.protocol == attributes.protocol &&
33
- sg.port_range_max == attributes.port_range_max &&
34
- sg.port_range_min == attributes.port_range_min &&
35
- sg.ethertype == attributes.ethertype &&
36
- (
37
- (
38
- attributes.remote_group_id.nil? &&
39
- sg.remote_ip_prefix == attributes.remote_ip
40
- ) ||
41
- (
42
- attributes.remote_ip.nil? &&
43
- sg.remote_group_id == attributes.remote_group_id
44
- )
45
- )
46
- end
47
- end
48
-
49
- def security_groups_on_tenant(tenant_name)
50
- Fog::Network[:openstack].security_groups.select{|sg| sg.tenant_id == tenant(tenant_name).id}
51
- end
52
-
53
- def security_groups_hash(tenant_name)
54
- sg_hash = Hash.new { |h,k| h[k] = {} }
55
-
56
- security_groups_on_tenant(tenant_name).each do |sg|
57
- sg_hash[sg.name]["rules"] = format_security_group(sg)
58
- sg_hash[sg.name]["description"] = sg.description
59
- end
60
- sg_hash
61
- end
62
-
63
- def format_security_group(security_group)
64
- security_group.security_group_rules.map do |rule|
65
- rule_hash = {}
66
- rule_hash["direction"] = rule.direction
67
- rule_hash["protocol"] = rule.protocol
68
- rule_hash["ethertype"] = rule.ethertype
69
-
70
- if rule.protocol == "icmp"
71
- rule_hash["type"] = rule.port_range_min
72
- rule_hash["code"] = rule.port_range_max
73
- elsif rule.port_range_max == rule.port_range_min
74
- rule_hash["port"] = rule.port_range_max
75
- else
76
- rule_hash["port_range_min"] = rule.port_range_min
77
- rule_hash["port_range_max"] = rule.port_range_max
78
- end
79
-
80
- if rule.remote_group_id
81
- response = Fog::Network[:openstack].get_security_group(rule.remote_group_id)
82
- rule_hash["remote_group"] = response.data[:body]["security_group"]["name"]
83
- else
84
- rule_hash["remote_ip"] = rule.remote_ip_prefix
85
- end
86
- rule_hash
4
+ def get(type)
5
+ case
6
+ when type == :yaml
7
+ Kakine::Resource::Yaml
8
+ when type == :openstack
9
+ Kakine::Resource::OpenStack
87
10
  end
88
11
  end
89
12
  end
@@ -0,0 +1,69 @@
1
+ module Kakine
2
+ class Resource
3
+ class OpenStack
4
+ class << self
5
+ def load_security_group
6
+ security_groups_hash.map do |sg|
7
+ Kakine::SecurityGroup.new(Kakine::Option.tenant_name, sg)
8
+ end
9
+ end
10
+
11
+ def tenant(tenant_name)
12
+ @@tenant ||= Kakine::Adapter.instance.tenants.detect{|t| t.name == tenant_name}
13
+ end
14
+
15
+ def security_group(tenant_name, security_group_name)
16
+ security_groups_on_tenant(tenant_name).detect{|sg| sg.name == security_group_name}
17
+ end
18
+
19
+ def security_groups_on_tenant(tenant_name)
20
+ Kakine::Adapter.instance.security_groups.select { |sg| sg.tenant_id == tenant(tenant_name).id }
21
+ end
22
+
23
+ def security_groups_hash
24
+ sg_hash = Hash.new { |h,k| h[k] = {} }
25
+
26
+ security_groups_on_tenant(Kakine::Option.tenant_name).each do |sg|
27
+ sg_hash[sg.name]["rules"] = format_security_group_rules(sg)
28
+ sg_hash[sg.name]["id"] = sg.id
29
+ sg_hash[sg.name]["description"] = sg.description
30
+ end
31
+ sg_hash
32
+ end
33
+
34
+ def format_security_group_rules(security_group)
35
+ security_group.rules.map do |rule|
36
+ rule_hash = {}
37
+ rule_hash["id"] = rule['id']
38
+ rule_hash["direction"] = rule['direction']
39
+ rule_hash["protocol"] = rule['protocol']
40
+ rule_hash["ethertype"] = rule['ethertype']
41
+ rule_hash.merge!(port_hash(rule))
42
+ rule_hash.merge!(remote_hash(rule))
43
+ end
44
+ end
45
+
46
+ def port_hash(rule)
47
+ case
48
+ when rule['protocol'] == "icmp"
49
+ { "type" => rule['port_range_min'], "code" => rule['port_range_max'] }
50
+ when rule['port_range_max'] == rule['port_range_min']
51
+ { "port" => rule['port_range_max'] }
52
+ else
53
+ { "port_range_min" => rule['port_range_min'], "port_range_max" => rule['port_range_max'] }
54
+ end
55
+ end
56
+
57
+ def remote_hash(rule)
58
+ case
59
+ when rule['remote_group_id']
60
+ response = Kakine::Adapter.instance.get_security_group(rule['remote_group_id'])
61
+ { "remote_group" => response.name }
62
+ else
63
+ { "remote_ip" => rule['remote_ip_prefix'] }
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,77 @@
1
+ module Kakine
2
+ class Resource
3
+ class Yaml
4
+ class << self
5
+ def load_security_group
6
+ load_yaml = yaml(Kakine::Option.yaml_name)
7
+ validate_file_input(load_yaml)
8
+ load_yaml.map { |sg| Kakine::SecurityGroup.new(Kakine::Option.tenant_name, sg) }
9
+ end
10
+
11
+ def yaml(filename)
12
+ YAML.load_file(filename).to_hash
13
+ end
14
+
15
+ def validate_file_input(load_sg)
16
+ load_sg.each do |sg|
17
+ validate_attributes(sg)
18
+ validate_rules(sg)
19
+ end
20
+ true
21
+ end
22
+
23
+ def validate_attributes(sg)
24
+ sg_name = sg[0]
25
+ case
26
+ when sg[1].nil?
27
+ raise(Kakine::ConfigureError, "#{sg_name}:rules and description is required")
28
+ when !sg[1].key?("rules")
29
+ raise(Kakine::ConfigureError, "#{sg_name}:rules is required")
30
+ when !sg[1].key?("description")
31
+ raise(Kakine::ConfigureError, "#{sg_name}:description is required")
32
+ end
33
+ end
34
+
35
+ def validate_rules(sg)
36
+ sg_name = sg[0]
37
+ sg[1]["rules"].each do |rule|
38
+ case
39
+ when !has_port?(rule)
40
+ raise(Kakine::ConfigureError, "#{sg_name}:rules port(icmp code) is required")
41
+ when !has_remote?(rule)
42
+ raise(Kakine::ConfigureError, "#{sg_name}:rules remote_ip or remote_group required")
43
+ when !has_direction?(rule)
44
+ raise(Kakine::ConfigureError, "#{sg_name}:rules direction is required")
45
+ when !has_protocol?(rule)
46
+ raise(Kakine::ConfigureError, "#{sg_name}:rules protocol is required")
47
+ when !has_ethertype?(rule)
48
+ raise(Kakine::ConfigureError, "#{sg_name}:rules ethertype is required")
49
+ end
50
+ end unless sg[1]["rules"].nil?
51
+ end
52
+
53
+ def has_port?(rule)
54
+ rule.key?("port") ||
55
+ ( rule.key?("port_range_max") && rule.key?("port_range_min") ) ||
56
+ ( rule.key?("type") && rule.key?("code") )
57
+ end
58
+
59
+ def has_remote?(rule)
60
+ rule.key?("remote_ip") || rule.key?("remote_group")
61
+ end
62
+
63
+ def has_direction?(rule)
64
+ rule.key?("direction")
65
+ end
66
+
67
+ def has_protocol?(rule)
68
+ rule.key?("protocol")
69
+ end
70
+
71
+ def has_ethertype?(rule)
72
+ rule.key?("ethertype")
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -1,80 +1,52 @@
1
1
  require 'json'
2
2
  module Kakine
3
3
  class SecurityGroup
4
- attr_reader :name, :tenant_id, :tenant_name, :description, :rules
4
+ attr_reader :id, :name, :tenant_name, :description, :rules
5
5
 
6
- def initialize(tenant_name, parameter)
7
- @name = parameter[0]
6
+ def initialize(tenant_name, params)
7
+ @name = params[0]
8
8
  @tenant_name = tenant_name
9
- @tenant_id = Kakine::Resource.tenant(tenant_name).id
10
- @description = parameter[1]["description"] || ""
11
- @rules = parameter[1]["rules"].map do |rule|
12
- SecurityRule.new(rule, @tenant_name, @name)
13
- end unless parameter[1]["rules"].nil?
14
- @rules ||= []
9
+ @id = params[1]["id"] || ""
10
+ @description = params[1]["description"] || ""
11
+ @rules = get_rule_instances(params) || []
15
12
  end
16
13
 
17
- def initialize_copy(obj)
18
- @rules = Marshal.load(Marshal.dump(obj.rules))
14
+ def tenant_id
15
+ Kakine::Resource.get(:openstack).tenant(@tenant_name).id
19
16
  end
20
17
 
21
18
  def ==(target_sg)
22
- instance_variables.reject{ |k| k == :@rules }.each do |val|
23
- return false unless self.instance_variable_get(val) == target_sg.instance_variable_get(val)
24
- end
25
- @rules.each do |rule|
26
- return false unless target_sg.find_by_rule(rule)
27
- end
28
- target_sg.rules.each do |rule|
29
- return false unless find_by_rule(rule)
30
- end
31
- true
19
+ same_group?(target_sg) && same_rule?(self, target_sg) && same_rule?(target_sg, self)
32
20
  end
33
21
 
34
22
  def !=(target_sg)
35
23
  !(self == target_sg)
36
24
  end
37
25
 
38
- def find_by_rule(target_rule)
39
- @rules.find { |rule| rule == target_rule }
26
+ def same_group?(target_sg)
27
+ %i(@name @tenant_name @description).all? do |val|
28
+ instance_variable_get(val) == target_sg.instance_variable_get(val)
29
+ end
40
30
  end
41
31
 
42
- def register!
43
- Kakine::Operation.create_security_group(self)
44
- @rules.each { |rule| rule.register! } if has_rules?
32
+ def same_rule?(a, b)
33
+ a.rules.all? do |rule|
34
+ b.find_by_rule(rule)
35
+ end
45
36
  end
46
37
 
47
- def unregister!
48
- Kakine::Operation.delete_security_group(self)
38
+ def get_rule_instances(params)
39
+ params[1]["rules"].map do |rule|
40
+ SecurityRule.new(rule, @tenant_name, @name)
41
+ end unless params[1]["rules"].nil?
49
42
  end
50
43
 
51
- def convergence!(target_sg)
52
- if @description != target_sg.description
53
- target_sg.unregister!
54
- register!
55
- else
56
- target_sg.rules.each do |rule|
57
- rule.unregister! unless find_by_rule(rule)
58
- end
59
- @rules.each do |rule|
60
- rule.register! unless target_sg.find_by_rule(rule)
61
- end
62
- end
44
+ def find_by_rule(target_rule)
45
+ @rules.find { |rule| rule == target_rule }
63
46
  end
64
47
 
65
48
  def has_rules?
66
49
  @rules.detect {|v| !v.nil?}
67
50
  end
68
-
69
- def get_default_rule_instance
70
- default_sg = self.clone
71
- default_sg.set_default_rule
72
- default_sg
73
- end
74
-
75
- def set_default_rule
76
- @rules = %w(IPv4 IPv6).map { |v| {"direction"=>"egress", "protocol" => nil, "port"=>nil, "remote_ip"=>nil, "ethertype"=>v } }.
77
- map{ |rule| SecurityRule.new(rule, @tenant_name, @name) }
78
- end
79
51
  end
80
52
  end
@@ -1,6 +1,6 @@
1
1
  module Kakine
2
2
  class SecurityRule
3
- attr_reader :direction, :protocol, :port_range_max, :port_range_min, :remote_ip, :remote_group, :remote_group_id, :ethertype
3
+ attr_reader :id, :direction, :protocol, :port_range_max, :port_range_min, :remote_ip, :remote_group, :ethertype
4
4
 
5
5
  def initialize(rule, tenant_name, sg_name)
6
6
  @tenant_name = tenant_name
@@ -11,47 +11,43 @@ module Kakine
11
11
  end
12
12
 
13
13
  @port_range_min, @port_range_max = *convert_port_format(rule)
14
- set_remote_security_group_id
14
+ end
15
15
 
16
+ def ==(target_sg)
17
+ %i(@direction @protocol @port_range_max @port_range_min @remote_ip @remote_group @ethertype).all? do |val|
18
+ self.instance_variable_get(val) == target_sg.instance_variable_get(val)
19
+ end
16
20
  end
17
21
 
18
- def register!
19
- Kakine::Operation.create_security_rule(@tenant_name, @sg_name, self)
22
+ def convert_port_format(rule)
23
+ unless format = port?(rule) || icmp?(rule) || range?(rule)
24
+ raise(Kakine::SecurityRuleError, "no match port format")
25
+ end
26
+ format
20
27
  end
21
28
 
22
- def unregister!
23
- Kakine::Operation.delete_security_rule(@tenant_name, @sg_name, self)
29
+ def port?(rule)
30
+ [rule['port'] ,rule['port']] if rule.has_key?('port')
24
31
  end
25
32
 
26
- def ==(target_sg)
27
- instance_variables.each do |val|
28
- unless self.instance_variable_get(val) == target_sg.instance_variable_get(val)
29
- return false
30
- end
33
+ def icmp?(rule)
34
+ if rule.has_key?('type') && rule.has_key?('code')
35
+ [rule['type'] ,rule['code']]
31
36
  end
32
- true
33
37
  end
34
38
 
35
- private
36
-
37
- def convert_port_format(rule)
38
- case
39
- when rule.has_key?('port')
40
- [rule['port'] ,rule['port']]
41
- when rule.has_key?('type'), rule.has_key?('code')
42
- [rule['type'] ,rule['code']]
43
- when rule.has_key?('port_range_max'), rule.has_key?('port_range_min')
39
+ def range?(rule)
40
+ if rule.has_key?('port_range_max') && rule.has_key?('port_range_min')
44
41
  [rule['port_range_min'] ,rule['port_range_max']]
45
- else
46
- raise "no match port format"
47
42
  end
48
43
  end
49
44
 
50
- def set_remote_security_group_id
51
- unless @remote_group.nil?
52
- remote_security_group = Kakine::Resource.security_group(@tenant_name, @remote_group)
53
- raise "not exists #{@remote_group}" unless remote_security_group
54
- @remote_group_id = remote_security_group.id
45
+ def remote_group_id
46
+ if !!@remote_group
47
+ unless remote_security_group = Kakine::Resource.get(:openstack).security_group(@tenant_name, @remote_group)
48
+ raise(Kakine::SecurityRuleError, "not exists #{@remote_group}")
49
+ end
50
+ remote_security_group.id
55
51
  end
56
52
  end
57
53
  end
@@ -1,3 +1,3 @@
1
1
  module Kakine
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kakine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SHIBATA Hiroshi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-05-26 00:00:00.000000000 Z
11
+ date: 2015-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: fog
14
+ name: yao
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 0.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 0.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: thor
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: hashdiff
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: bundler
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -128,14 +114,19 @@ files:
128
114
  - kakine.gemspec
129
115
  - lib/kakine.rb
130
116
  - lib/kakine/adapter.rb
117
+ - lib/kakine/adapter/base.rb
131
118
  - lib/kakine/adapter/mock.rb
132
119
  - lib/kakine/adapter/real.rb
120
+ - lib/kakine/builder.rb
133
121
  - lib/kakine/cli.rb
134
- - lib/kakine/operation.rb
122
+ - lib/kakine/config.rb
123
+ - lib/kakine/director.rb
124
+ - lib/kakine/option.rb
135
125
  - lib/kakine/resource.rb
126
+ - lib/kakine/resource/openstack.rb
127
+ - lib/kakine/resource/yaml.rb
136
128
  - lib/kakine/security_group.rb
137
129
  - lib/kakine/security_rule.rb
138
- - lib/kakine/validate.rb
139
130
  - lib/kakine/version.rb
140
131
  homepage: https://github.com/hsbt/kakine
141
132
  licenses:
@@ -157,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
148
  version: '0'
158
149
  requirements: []
159
150
  rubyforge_project:
160
- rubygems_version: 2.4.7
151
+ rubygems_version: 2.5.0
161
152
  signing_key:
162
153
  specification_version: 4
163
154
  summary: Security Group configuration tool for OpenStack.
@@ -1,38 +0,0 @@
1
- module Kakine
2
- class Operation
3
- class << self
4
- def adapter
5
- @@adapter ||= Kakine::Adapter.get_instance
6
- end
7
-
8
- def create_security_group(sg)
9
- attributes = {name: sg.name, description: sg.description, tenant_id: sg.tenant_id}
10
- security_group_id = adapter.create_security_group(attributes)
11
-
12
- #delete default rule
13
- sg.get_default_rule_instance.rules.each { |rule| rule.unregister! } unless adapter.instance_of?(Kakine::Adapter::Mock)
14
- security_group_id
15
- end
16
-
17
- def delete_security_group(sg)
18
- security_group = Kakine::Resource.security_group(sg.tenant_name, sg.name)
19
- adapter.delete_security_group(security_group.id)
20
- end
21
-
22
- def create_security_rule(tenant_name, sg_name, rule)
23
- security_group_id = if adapter.instance_of?(Kakine::Adapter::Mock)
24
- "[Mock] #{sg_name} ID"
25
- else
26
- Kakine::Resource.security_group(tenant_name, sg_name).id
27
- end
28
- adapter.create_rule(security_group_id, rule.direction, rule)
29
- end
30
-
31
- def delete_security_rule(tenant_name, sg_name, rule)
32
- security_group = Kakine::Resource.security_group(tenant_name, sg_name)
33
- security_group_rule = Kakine::Resource.security_group_rule(security_group, rule)
34
- adapter.delete_rule(security_group_rule.id)
35
- end
36
- end
37
- end
38
- end
@@ -1,42 +0,0 @@
1
- module Kakine
2
- class Validate
3
- class << self
4
- def validate_file_input(load_sg)
5
- err = []
6
- load_sg.each do |sg|
7
- err << validate_attributes(sg)
8
- err << validate_rules(sg)
9
- end
10
- return true unless err.detect {|e| !e.nil? }
11
- err.map { |m| puts m unless m.nil? }
12
- false
13
- end
14
-
15
- def validate_attributes(sg)
16
- case
17
- when sg[1].nil?
18
- "[error] #{sg[0]}:rules and description is required"
19
- when !sg[1].key?("rules")
20
- "[error] #{sg[0]}:rules is required"
21
- when !sg[1].key?("description")
22
- "[error] #{sg[0]}:description is required"
23
- end
24
- end
25
-
26
- def validate_rules(sg)
27
- sg[1]["rules"].each do |rule|
28
- if !rule.key?("port") &&
29
- (!rule.key?("port_range_max") || !rule.key?("port_range_min")) &&
30
- (!rule.key?("type") || !rule.key?("code"))
31
- return "[error] #{sg[0]}:rules port(icmp code) is required"
32
- elsif !rule.key?("remote_ip") && !rule.key?("remote_group")
33
- return "[error] #{sg[0]}:rules remote_ip or remote_group required"
34
- elsif col = %w(direction protocol ethertype).find { |k| !rule.key?(k) }
35
- return "[error] #{sg[0]}:rules #{col} is required"
36
- end
37
- end unless sg[1]["rules"].nil?
38
- nil
39
- end
40
- end
41
- end
42
- end