kakine 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4768538b225d648ebf64a3eb52c7a2841cb14334
4
- data.tar.gz: 5361d5d1eb968a8d238910ff5995fb4ee3b53592
3
+ metadata.gz: d3f0de2336304ed3476ccfc1b63e2bdc01a9c1cd
4
+ data.tar.gz: c1b97adbc29b5a659b1fb38b79f04dcb596a1f53
5
5
  SHA512:
6
- metadata.gz: 5b8b3bc37780557a3c8fe2edd9209aa3f7f36e5de23bd0135f68aff7b541401609e4f77f70c04a3d0a6c803c4403c9d323be2e6d04bd2ed83ca5a620f4573cec
7
- data.tar.gz: 5f8b2b5c7389bd4faea0752ff304dada6e433255d5dee7d926c7ec15df4d8281edab36b65597245e36f1157324caa7743c487354aa5ef5d13b4485de3b39bb88
6
+ metadata.gz: c402eeb05b5d24368f1b66694965fa8fac9116a8354c11a69a33c5bc64695f9d107ed63072f523a1da22d9520bf86eed35bedff78e1811da249ae91b5ccd1c11
7
+ data.tar.gz: a2c41d220786673210a397f27d049f7d52c6ec5ae5aa623361eb08fd62d8634d7d70350d3a303f931ff2799657d9c1295dc28df9432d065ec9ed61ed9ae2fbde
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Kakine
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/hsbt/kaname.png)](https://travis-ci.org/hsbt/kaname)
3
+ [![Build Status](https://secure.travis-ci.org/hsbt/kakine.png)](https://travis-ci.org/hsbt/kakine)
4
4
 
5
5
  Kakine(垣根) is configuration management tool of Security Group on OpenStack.
6
6
 
@@ -26,19 +26,22 @@ You can define Security Group configuration for OpenStack via YAML format. Like
26
26
 
27
27
  ```yaml
28
28
  app:
29
- - direction: ingress
30
- protocol: tcp
31
- port: 443
32
- remote_ip: 0.0.0.0/0
33
- - direction: ingress
34
- protocol: tcp
35
- port: 80
36
- remote_ip: 0.0.0.0/0
29
+ rules:
30
+ - direction: ingress
31
+ protocol: tcp
32
+ port: 443
33
+ remote_ip: 0.0.0.0/0
34
+ - direction: ingress
35
+ protocol: tcp
36
+ port: 80
37
+ remote_ip: 0.0.0.0/0
38
+ description: app rules
37
39
  rails:
38
- - direction: ingress
39
- protocol: tcp
40
- port: 3000
41
- remote_ip: 0.0.0.0/0
40
+ rules:
41
+ - direction: ingress
42
+ protocol: tcp
43
+ port: 3000
44
+ remote_ip: 0.0.0.0/0
42
45
  ```
43
46
 
44
47
  You need to put fog configuration to home directory.
@@ -55,9 +58,9 @@ default:
55
58
  run following command.
56
59
 
57
60
  ```sh
58
- $ kakine show tenant_name # show Security Group of tenant_name
59
- $ kaname apply tenant_name --dryrun # You can see all of invoke commands(dryrun)
60
- $ kaname apply tenant_name # apply configuration into OpenStack
61
+ $ 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
64
  ```
62
65
 
63
66
  You can create or change Security Group on targeting tenant.
@@ -65,7 +68,7 @@ You can create or change Security Group on targeting tenant.
65
68
  If you need to initialize your Security Gruop, you can get it via following command:
66
69
 
67
70
  ```sh
68
- $ kaname show tenant_name > tenant_name.yaml
71
+ $ kaname show -t tenant_name > tenant_name.yaml
69
72
  ```
70
73
 
71
74
  ## Development
@@ -1,7 +1,12 @@
1
1
  require "kakine/version"
2
2
  require 'kakine/cli'
3
+ require 'kakine/cli/operation'
3
4
  require 'kakine/adapter'
4
5
  require 'kakine/resource'
6
+ require 'kakine/hash_sort'
7
+ require 'kakine/security_group'
8
+ require 'kakine/diff_parser'
5
9
 
6
10
  module Kakine
7
11
  end
12
+
@@ -5,6 +5,7 @@ require 'hashdiff'
5
5
 
6
6
  module Kakine
7
7
  class CLI < Thor
8
+
8
9
  option :tenant, type: :string, aliases: '-t'
9
10
  desc 'show', 'show Security Groups specified tenant'
10
11
  def show
@@ -22,49 +23,57 @@ module Kakine
22
23
  Kakine::Adapter::Real.new
23
24
  end
24
25
 
26
+ operation = Kakine::CLI::Operation.new
27
+ operation.set_adapter(adapter)
28
+
25
29
  filename = options[:filename] ? options[:filename] : "#{options[:tenant]}.yaml"
26
- diffs = HashDiff.diff(Kakine::Resource.security_groups_hash(options[:tenant]), Kakine::Resource.yaml(filename))
30
+
31
+ security_groups = []
32
+ delay_create = []
33
+
34
+ diffs = HashDiff.diff(
35
+ Kakine::Resource.security_groups_hash(options[:tenant]),
36
+ Kakine::Resource.yaml(filename)
37
+ )
27
38
 
28
39
  diffs.each do |diff|
29
- sg_name, rule_modification = *diff[1].scan(/^([\w-]+)(\[\d\])?/)[0]
40
+ security_groups << Kakine::SecurityGroup.new(options[:tenant], diff)
41
+ end
30
42
 
31
- if rule_modification # foo[2]
32
- security_group = Kakine::Resource.security_group(options[:tenant], sg_name)
33
- if diff[2]["remote_group"]
34
- remote_security_group = Kakine::Resource.security_group(options[:tenant], diff[2].delete("remote_group"))
35
- diff[2]["remote_group_id"] = remote_security_group.id
36
- end
37
- case diff[0]
38
- when "+"
39
- diff[2].merge!({"ethertype" => "IPv4", "tenant_id" => Kakine::Resource.tenant(options[:tenant]).id})
40
- adapter.create_rule(security_group.id, diff[2]["direction"], diff[2])
41
- when "-"
42
- security_group_rule = Kakine::Resource.security_group_rule(security_group, diff[2])
43
- adapter.delete_rule(security_group_rule.id)
43
+ security_groups.each do |sg|
44
+ if sg.update_rule? # foo[2]
45
+ case
46
+ when sg.add?
47
+ operation.create_security_rule(sg)
48
+ when sg.delete?
49
+ operation.delete_security_rule(sg)
50
+ when sg.update_attr?
51
+ pre_sg = sg.get_prev_instance
52
+ operation.delete_security_rule(pre_sg)
53
+ delay_create << sg # avoid duplication entry
44
54
  else
45
55
  raise
46
56
  end
47
57
  else # foo
48
- case diff[0]
49
- when "+"
50
- attributes = {name: sg_name, description: "", tenant_id: Kakine::Resource.tenant(options[:tenant]).id}
51
- security_group_id = adapter.create_security_group(attributes)
52
- diff[2].each do |rule|
53
- rule.merge!({"ethertype" => "IPv4", "tenant_id" => Kakine::Resource.tenant(options[:tenant]).id})
54
- if rule["remote_group"]
55
- remote_security_group = Kakine::Resource.security_group(options[:tenant], rule.delete("remote_group"))
56
- rule["remote_group_id"] = remote_security_group.id
57
- end
58
- adapter.create_rule(security_group_id, rule["direction"], rule)
59
- end if diff[2]
60
- when "-"
61
- security_group = Kakine::Resource.security_group(options[:tenant], sg_name)
62
- adapter.delete_security_group(security_group.id)
58
+ case
59
+ when sg.add?
60
+ security_group_id = operation.create_security_group(sg)
61
+ operation.create_security_rule(sg, security_group_id)
62
+ when sg.delete?
63
+ operation.delete_security_group(sg)
64
+ when sg.update_attr?
65
+ operation.delete_security_group(sg)
66
+ security_group_id = operation.create_security_group(sg)
67
+ operation.create_security_rule(sg, security_group_id)
63
68
  else
64
69
  raise
65
70
  end
66
71
  end
67
72
  end
73
+ # update rule attributes delay create
74
+ delay_create.each do |sg|
75
+ operation.create_security_rule(sg)
76
+ end
68
77
  end
69
78
  end
70
79
  end
@@ -0,0 +1,44 @@
1
+ module Kakine
2
+ class CLI < Thor
3
+ class Operation
4
+ def set_adapter(adapter)
5
+ @adapter = adapter
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
+ delete_sg = sg.clone
14
+ delete_sg.set_default_rules
15
+
16
+ delete_security_rule(delete_sg) unless @adapter.instance_of?(Kakine::Adapter::Mock)
17
+ security_group_id
18
+ end
19
+
20
+ def delete_security_group(sg)
21
+ security_group = Kakine::Resource.security_group(sg.tenant_name, sg.name)
22
+ @adapter.delete_security_group(security_group.id)
23
+ end
24
+
25
+ def create_security_rule(sg, security_group_id=nil)
26
+ if security_group_id.nil?
27
+ security_group = Kakine::Resource.security_group(sg.tenant_name, sg.name)
28
+ security_group_id = security_group.id
29
+ end
30
+ sg.rules.each do |rule|
31
+ @adapter.create_rule(security_group_id, rule["direction"], rule)
32
+ end if sg.has_rules?
33
+ end
34
+
35
+ def delete_security_rule(sg)
36
+ security_group = Kakine::Resource.security_group(sg.tenant_name, sg.name)
37
+ sg.rules.each do |rule|
38
+ security_group_rule = Kakine::Resource.security_group_rule(security_group, rule)
39
+ @adapter.delete_rule(security_group_rule.id)
40
+ end if sg.has_rules?
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,88 @@
1
+ module Kakine
2
+ class DiffParser
3
+ @diff = ""
4
+ class << self
5
+ def parse_parameters(tenant_name, diff)
6
+ @diff = diff
7
+
8
+ registered_sg = Kakine::Resource.security_groups_hash(tenant_name)
9
+ if ["+", "-"].include?(parse_transaction_type)
10
+ if unit_is_security_group?
11
+ rules = parse_security_group["rules"]
12
+ description = parse_security_group["description"]
13
+ elsif unit_is_security_rule?
14
+ rules = [parse_security_group_rule]
15
+ description = registered_sg[parse_security_group_name]["description"]
16
+ elsif unit_is_description?
17
+ raise "description is not exists"
18
+ end
19
+ else
20
+ regex_update_description = /^[\w-]+\.description$/
21
+ regex_update_rules = /^[\w-]+\.rules$/
22
+ regex_update_attr = /^[\w-]+.[\w]+\[(\d)\].([\w]+)$/
23
+
24
+ if parse_target_object_name.match(regex_update_description)
25
+ rules = registered_sg[parse_security_group_name]["rules"]
26
+ description = parse_after_description
27
+ elsif parse_target_object_name.match(regex_update_rules)
28
+ rules = parse_after_rules
29
+ description = registered_sg[parse_security_group_name]["description"]
30
+ elsif m = parse_target_object_name.match(regex_update_attr)
31
+ rules = [registered_sg[parse_security_group_name]["rules"][m[1].to_i]]
32
+ prev_rules = Marshal.load(Marshal.dump(rules)) # backup before value
33
+ rules[0][m[2]] = parse_after_attr
34
+ description = registered_sg[parse_security_group_name]["description"]
35
+ end
36
+ end
37
+ rules ||= []
38
+
39
+ {
40
+ target_object_name: parse_target_object_name,
41
+ name: parse_security_group_name,
42
+ transaction_type: parse_transaction_type,
43
+ tenant_id: Kakine::Resource.tenant(tenant_name).id,
44
+ tenant_name: tenant_name,
45
+ description: description,
46
+ rules: rules,
47
+ prev_rules: prev_rules
48
+ }
49
+ end
50
+
51
+ def parse_security_group_name
52
+ parse_target_object_name.split(/[\.\[]/, 2)[0]
53
+ end
54
+
55
+
56
+ def parse_transaction_type
57
+ @diff[0]
58
+ end
59
+
60
+ def parse_target_object_name
61
+ @diff[1]
62
+ end
63
+
64
+ def parse_security_group
65
+ @diff[2]
66
+ end
67
+ alias :parse_security_group_rule :parse_security_group
68
+
69
+ def parse_after_attr
70
+ @diff[3]
71
+ end
72
+ alias :parse_after_description :parse_after_attr
73
+ alias :parse_after_rules :parse_after_attr
74
+
75
+ def unit_is_security_group?
76
+ parse_security_group && parse_security_group["rules"]
77
+ end
78
+
79
+ def unit_is_security_rule?
80
+ !(parse_security_group_rule.nil? || unit_is_description?)
81
+ end
82
+
83
+ def unit_is_description?
84
+ parse_target_object_name.index('description')
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,13 @@
1
+ class Hash
2
+ def sg_rules_sort
3
+ self.each do |sg|
4
+ sg[1]['rules'].sort_by! do |rule|
5
+ rule.inject(0) do |ascii,(k,v)|
6
+ ascii += v.ord.to_i unless v.nil?
7
+ ascii
8
+ end
9
+ end unless sg[1].nil? || sg[1]['rules'].nil?
10
+ end
11
+ Hash[self]
12
+ end
13
+ end
@@ -1,13 +1,13 @@
1
+ require 'kakine/hash_sort'
1
2
  module Kakine
2
3
  class Resource
3
4
  class << self
4
5
  def yaml(filename)
5
- YAML.load_file(filename).to_hash
6
+ YAML.load_file(filename).to_hash.sg_rules_sort
6
7
  end
7
8
 
8
9
  def tenant(tenant_name)
9
- tenants = Fog::Identity[:openstack].tenants
10
- tenants.detect{|t| t.name == tenant_name}
10
+ @tenant ||= Fog::Identity[:openstack].tenants.detect{|t| t.name == tenant_name}
11
11
  end
12
12
 
13
13
  def security_group(tenant_name, security_group_name)
@@ -24,24 +24,31 @@ module Kakine
24
24
  sg.protocol == attributes["protocol"] &&
25
25
  sg.port_range_max == attributes["port_range_max"] &&
26
26
  sg.port_range_min == attributes["port_range_min"] &&
27
- sg.remote_ip_prefix == attributes["remote_ip"] &&
28
- sg.remote_group_id == attributes["remote_group_id"]
27
+ (
28
+ (
29
+ sg.remote_ip_prefix == attributes["remote_ip"] &&
30
+ sg.ethertype == attributes["ethertype"]
31
+ ) ||
32
+ (
33
+ sg.remote_group_id == attributes["remote_group_id"] &&
34
+ !attributes["remote_group_id"].nil?
35
+ )
36
+ )
29
37
  end
30
38
  end
31
39
 
32
40
  def security_groups_on_tenant(tenant_name)
33
- security_groups = Fog::Network[:openstack].security_groups
34
- security_groups.select{|sg| sg.tenant_id == tenant(tenant_name).id}
41
+ Fog::Network[:openstack].security_groups.select{|sg| sg.tenant_id == tenant(tenant_name).id}
35
42
  end
36
43
 
37
44
  def security_groups_hash(tenant_name)
38
- sg_hash = {}
45
+ sg_hash = Hash.new { |h,k| h[k] = {} }
39
46
 
40
47
  security_groups_on_tenant(tenant_name).each do |sg|
41
- sg_hash[sg.name] = format_security_group(sg)
48
+ sg_hash[sg.name]["rules"] = format_security_group(sg)
49
+ sg_hash[sg.name]["description"] = sg.description
42
50
  end
43
-
44
- sg_hash
51
+ sg_hash.sg_rules_sort
45
52
  end
46
53
 
47
54
  def format_security_group(security_group)
@@ -49,7 +56,6 @@ module Kakine
49
56
 
50
57
  security_group.security_group_rules.each do |rule|
51
58
  rule_hash = {}
52
-
53
59
  rule_hash["direction"] = rule.direction
54
60
  rule_hash["protocol"] = rule.protocol
55
61
 
@@ -65,11 +71,10 @@ module Kakine
65
71
  rule_hash["remote_group"] = response.data[:body]["security_group"]["name"]
66
72
  else
67
73
  rule_hash["remote_ip"] = rule.remote_ip_prefix
74
+ rule_hash["ethertype"] = rule.ethertype
68
75
  end
69
-
70
76
  rules << rule_hash
71
77
  end
72
-
73
78
  rules
74
79
  end
75
80
  end
@@ -0,0 +1,76 @@
1
+ module Kakine
2
+ class SecurityGroup
3
+ attr_reader :target_object_name, :name, :transaction_type, :tenant_id, :tenant_name, :description, :rules, :prev_rules
4
+
5
+ def initialize(tenant_name, diff)
6
+ unset_security_rules
7
+ Kakine::DiffParser.parse_parameters(tenant_name, diff).each do|k,v|
8
+ instance_variable_set(eval(":@#{k.to_s}"), v)
9
+ end
10
+ set_remote_security_group_id
11
+ end
12
+
13
+ def initialize_copy(obj)
14
+ @rules = Marshal.load(Marshal.dump(obj.rules))
15
+ @prev_rules = Marshal.load(Marshal.dump(obj.prev_rules))
16
+ unset_security_rules
17
+ end
18
+
19
+ def has_rules?
20
+ @rules.detect {|v| !v.nil? && v.size > 0}
21
+ end
22
+
23
+ def add?
24
+ @transaction_type == "+"
25
+ end
26
+
27
+ def delete?
28
+ @transaction_type == "-"
29
+ end
30
+
31
+ def update_attr?
32
+ @transaction_type == "~"
33
+ end
34
+
35
+ def update_rule?
36
+ !@target_object_name.split(/[\[]/, 2)[1].nil?
37
+ end
38
+
39
+ def get_prev_instance
40
+ prev_sg = self.clone
41
+ prev_sg.add_security_rules(@prev_rules)
42
+ prev_sg
43
+ end
44
+
45
+ def set_default_rules
46
+ unset_security_rules
47
+ ["IPv4", "IPv6"].each do |ip|
48
+ add_security_rules({"direction"=>"egress", "protocol"=>nil, "port"=>nil, "remote_ip"=>nil, "ethertype"=>ip})
49
+ end
50
+ end
51
+
52
+ def add_security_rules(rule)
53
+ case
54
+ when rule.instance_of?(Array)
55
+ @rules = rule
56
+ when rule.instance_of?(Hash)
57
+ @rules << rule
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def unset_security_rules
64
+ @rules = []
65
+ end
66
+
67
+ def set_remote_security_group_id
68
+ @rules.each do |rule|
69
+ unless rule['remote_group'].nil?
70
+ remote_security_group = Kakine::Resource.security_group(@tenant_name, rule.delete("remote_group"))
71
+ rule["remote_group_id"] = remote_security_group.id
72
+ end
73
+ end if has_rules?
74
+ end
75
+ end
76
+ end
@@ -1,3 +1,3 @@
1
1
  module Kakine
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kakine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.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-04-27 00:00:00.000000000 Z
11
+ date: 2015-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fog
@@ -131,7 +131,11 @@ files:
131
131
  - lib/kakine/adapter/mock.rb
132
132
  - lib/kakine/adapter/real.rb
133
133
  - lib/kakine/cli.rb
134
+ - lib/kakine/cli/operation.rb
135
+ - lib/kakine/diff_parser.rb
136
+ - lib/kakine/hash_sort.rb
134
137
  - lib/kakine/resource.rb
138
+ - lib/kakine/security_group.rb
135
139
  - lib/kakine/version.rb
136
140
  homepage: https://github.com/hsbt/kakine
137
141
  licenses:
@@ -153,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
157
  version: '0'
154
158
  requirements: []
155
159
  rubyforge_project:
156
- rubygems_version: 2.4.6
160
+ rubygems_version: 2.4.7
157
161
  signing_key:
158
162
  specification_version: 4
159
163
  summary: Security Group configuration tool for OpenStack.