milc 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7c239037f0df6a192cac2c900393eb454f12fc73
4
+ data.tar.gz: 82cb6fc05b307fcb1e84fc503262ffdae6762a01
5
+ SHA512:
6
+ metadata.gz: 2fe22d49727f450be4370099bc0756627e931e6475862d88e2faa0d0c7c90bffe930966c23d3f7083ae104c34fd846ece2da91ebc81e7a787fef37fbe9ec7fe2
7
+ data.tar.gz: 10d7b3a2ba518e4dfd195de41101d546cd14988d4a06e273acf5b8036eee8bc30d7545571ea8fca10079f9f052148097eb8a285213804673b4d9b85ac474215b
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in milc.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 akm
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # Milc
2
+
3
+ Milc means "Magellan Infrastructure Library and Command".
4
+
5
+ This gem supports portability from command to ruby library in order to realize automated orchestration.
6
+
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'milc'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install milc
23
+
24
+ ## Usage
25
+
26
+ TODO: Write usage instructions here
27
+
28
+ ## Development
29
+
30
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment. Run `bundle exec milc` to use the code located in this directory, ignoring other installed copies of this gem.
31
+
32
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
33
+
34
+ ## Contributing
35
+
36
+ 1. Fork it ( https://github.com/[my-github-username]/milc/fork )
37
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
38
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
39
+ 4. Push to the branch (`git push origin my-new-feature`)
40
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
8
+
9
+ module Bundler
10
+ class GemHelper
11
+ def version_tag
12
+ d = File.basename(File.dirname(__FILE__))
13
+ "#{d}/#{version}"
14
+ end
15
+ end
16
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "milc"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/exe/milc ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "milc"
data/lib/milc/base.rb ADDED
@@ -0,0 +1,103 @@
1
+ # coding: utf-8
2
+
3
+ require "milc"
4
+
5
+ require 'json'
6
+ require 'erb'
7
+ require 'yaml'
8
+ require 'optparse'
9
+ require 'shellwords'
10
+
11
+ require 'logger_pipe'
12
+
13
+ def YAML.load_file_with_erb(yaml_path)
14
+ # config file example
15
+ # https://github.com/tengine/magellan-infra/blob/master/ansible/magellan-production_nebula-001/files/conf/nebula-staging/common.conf
16
+ erb = ERB.new(IO.read(yaml_path))
17
+ erb.filename = yaml_path
18
+ text = erb.result
19
+ YAML.load(text)
20
+ end
21
+
22
+ module Milc
23
+ module Base
24
+ include Milc::Dsl::Gcloud
25
+ include Milc::Dsl::Mgcloud
26
+
27
+ include Milc::Dsl::Ansible
28
+
29
+ def logger
30
+ Milc.logger
31
+ end
32
+
33
+ def execute(cmd)
34
+ res = LoggerPipe.run(logger, cmd, dry_run: Milc.dry_run)
35
+ block_given? ? yield(res) : res
36
+ end
37
+
38
+ def load_from_yaml(yaml_path)
39
+ @config = YAML.load_file_with_erb(yaml_path)
40
+ load_config
41
+ end
42
+
43
+ attr_reader :config
44
+ attr_reader :project, :nebula
45
+ attr_reader :network_base, :region, :new_relic_license_key
46
+
47
+ def dry_run
48
+ Milc.dry_run
49
+ end
50
+
51
+ def load_config
52
+ @project = config['PROJECT'] || ENV['PROJECT']
53
+ @nebula = config['NEBULA'] || ENV['NEBULA']
54
+ @network_base = config['NETWORK_BASE'] || ENV['NETWORK_BASE']
55
+ @region =config['REGION'] || ENV['REGION']
56
+ @new_relic_license_key = config['NEW_RELIC_LICENSE_KEY'] || ENV['NEW_RELIC_LICENSE_KEY']
57
+ end
58
+
59
+ def show_help_and_exit1
60
+ ## シェルスクリプトのUsage
61
+ $stderr.puts help_message
62
+ exit 1
63
+ end
64
+
65
+ def help_message
66
+ ## スクリプト名
67
+ cmdname = File.basename($0) # $PROGRAM_NAME を推奨
68
+ ## シェルスクリプトのUsage
69
+ "Usage: #{cmdname} -c CONF_FILE"
70
+ end
71
+
72
+ def command_options
73
+ "nVc:" # n と V と c: は必須
74
+ end
75
+
76
+ def load_options(options)
77
+ end
78
+
79
+ def setup(args)
80
+ # ARGV.getopts については以下を参照
81
+ # http://d.hatena.ne.jp/zariganitosh/20140819/ruby_optparser_true_power
82
+ # http://docs.ruby-lang.org/ja/2.1.0/method/OptionParser=3a=3aArguable/i/getopts.html
83
+ args.extend(OptionParser::Arguable) unless args.is_a?(OptionParser::Arguable)
84
+ options = args.getopts(command_options)
85
+ show_help_and_exit1 unless args.empty?
86
+
87
+ Milc.dry_run = !!options["n"]
88
+ Milc.verbose = !!options["V"]
89
+
90
+ show_help_and_exit1 unless options["c"]
91
+
92
+ load_from_yaml(options["c"])
93
+ load_options(options)
94
+ end
95
+
96
+ def run(args)
97
+ setup(args)
98
+ process
99
+ exit 0
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,14 @@
1
+ require "milc/dsl"
2
+
3
+ module Milc::Dsl
4
+ module Ansible
5
+
6
+ def ansible_playbook(cmd, &block)
7
+ # https://github.com/mitchellh/vagrant/blob/0098b7604d071948fd37b16dd10b87b6df49b624/plugins/provisioners/ansible/provisioner.rb#L58
8
+ command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook #{cmd}"
9
+ command << " -vvvv" if Milc.verbose
10
+ execute(command, &block)
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ require "milc/dsl"
2
+
3
+ module Milc::Dsl
4
+ module Gcloud
5
+
6
+ def gcloud(cmd, &block)
7
+ cmd << " --project #{project}" unless cmd =~ /\s\-\-project[\s\=]/
8
+ execute("gcloud #{cmd}", &block)
9
+ end
10
+
11
+ def json_gcloud(cmd)
12
+ r = gcloud(cmd + " --format json")
13
+ res = r.nil? ? nil : JSON.parse(r)
14
+ block_given? ? yield(res) : res
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ require "milc/dsl"
2
+
3
+ module Milc::Dsl
4
+ module Mgcloud
5
+
6
+ def mgcloud(cmd, attrs = {}, &block)
7
+ service, resource, action, cmd_args = cmd.lstrip.split(/\s+/, 4)
8
+ resource = Milc::Gcloud::Resource.lookup(project, service, resource)
9
+ resource.send(action.gsub(/-/, '_'), cmd_args, attrs, &block)
10
+ end
11
+
12
+ end
13
+ end
data/lib/milc/dsl.rb ADDED
@@ -0,0 +1,12 @@
1
+ # coding: utf-8
2
+
3
+ require "milc"
4
+
5
+ module Milc
6
+ module Dsl
7
+ autoload :Gcloud , 'milc/dsl/gcloud'
8
+ autoload :Mgcloud , 'milc/dsl/mgcloud'
9
+
10
+ autoload :Ansible, 'milc/dsl/ansible'
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ require "milc/gcloud/backend"
2
+
3
+ require 'logger'
4
+
5
+ require 'logger_pipe'
6
+
7
+ module Milc
8
+ module Gcloud
9
+ module Backend
10
+ class GcloudCommand
11
+
12
+ def execute(cmd)
13
+ res = LoggerPipe.run(Milc.logger, cmd, dry_run: Milc.dry_run)
14
+ block_given? ? yield(res) : res
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ # coding: utf-8
2
+
3
+ require "milc/gcloud"
4
+
5
+ module Milc
6
+ module Gcloud
7
+ module Backend
8
+ autoload :GcloudCommand, 'milc/gcloud/backend/gcloud_command'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,213 @@
1
+ compute:
2
+ addresses:
3
+ commands:
4
+ - create
5
+ - delete
6
+ - describe
7
+ - list
8
+ backend-services:
9
+ commands:
10
+ - add-backend
11
+ - create
12
+ - delete
13
+ - describe
14
+ - edit
15
+ - get-health
16
+ - list
17
+ - remove-backend
18
+ - update
19
+ - update-backend
20
+ disk-types:
21
+ commands:
22
+ - describe
23
+ - list
24
+ disks:
25
+ commands:
26
+ - create
27
+ - delete
28
+ - describe
29
+ - list
30
+ - snapshot
31
+ firewall-rules:
32
+ commands:
33
+ - create
34
+ - delete
35
+ - describe
36
+ - list
37
+ - update
38
+ forwarding-rules:
39
+ commands:
40
+ - create
41
+ - delete
42
+ - describe
43
+ - list
44
+ - set-target
45
+ http-health-checks:
46
+ commands:
47
+ - create
48
+ - delete
49
+ - describe
50
+ - list
51
+ - update
52
+ images:
53
+ commands:
54
+ - create
55
+ - delete
56
+ - deprecate
57
+ - describe
58
+ - list
59
+ instance-templates:
60
+ commands:
61
+ - create
62
+ - delete
63
+ - describe
64
+ - list
65
+ instances:
66
+ commands:
67
+ - add-access-config
68
+ - add-metadata
69
+ - add-tags
70
+ - attach-disk
71
+ - create
72
+ - delete
73
+ - delete-access-config
74
+ - describe
75
+ - detach-disk
76
+ - get-serial-port-output
77
+ - list
78
+ - remove-metadata
79
+ - remove-tags
80
+ - reset
81
+ - set-disk-auto-delete
82
+ - set-scheduling
83
+ machine-types:
84
+ commands:
85
+ - describe
86
+ - list
87
+ networks:
88
+ commands:
89
+ - create
90
+ - delete
91
+ - describe
92
+ - list
93
+ operations:
94
+ commands:
95
+ - describe
96
+ - list
97
+ project-info:
98
+ commands:
99
+ - add-metadata
100
+ - describe
101
+ - remove-metadata
102
+ - set-usage-bucket
103
+ regions:
104
+ commands:
105
+ - describe
106
+ - list
107
+ routes:
108
+ commands:
109
+ - create
110
+ - delete
111
+ - describe
112
+ - list
113
+ snapshots:
114
+ commands:
115
+ - delete
116
+ - describe
117
+ - list
118
+ target-http-proxies:
119
+ commands:
120
+ - create
121
+ - delete
122
+ - describe
123
+ - list
124
+ - update
125
+ target-instances:
126
+ commands:
127
+ - create
128
+ - delete
129
+ - describe
130
+ - list
131
+ target-pools:
132
+ commands:
133
+ - add-health-checks
134
+ - add-instances
135
+ - create
136
+ - delete
137
+ - describe
138
+ - get-health
139
+ - list
140
+ - remove-health-checks
141
+ - remove-instances
142
+ - set-backup
143
+ url-maps:
144
+ commands:
145
+ - add-host-rule
146
+ - add-path-matcher
147
+ - create
148
+ - delete
149
+ - describe
150
+ - edit
151
+ - list
152
+ - remove-host-rule
153
+ - remove-path-matcher
154
+ - set-default-service
155
+ zones:
156
+ commands:
157
+ - describe
158
+ - list
159
+ sql:
160
+ backups:
161
+ commands:
162
+ - describe
163
+ - list
164
+ flags:
165
+ commands:
166
+ - list
167
+ instances:
168
+ commands:
169
+ - clone
170
+ - create
171
+ - delete
172
+ - describe
173
+ - export
174
+ - import
175
+ - list
176
+ - patch
177
+ - promote-replica
178
+ - reset-ssl-config
179
+ - restart
180
+ - restore-backup
181
+ - set-root-password
182
+ operations:
183
+ commands:
184
+ - describe
185
+ - list
186
+ - wait
187
+ ssl-certs:
188
+ commands:
189
+ - create
190
+ - delete
191
+ - describe
192
+ - list
193
+ tiers:
194
+ commands:
195
+ - list
196
+ dns:
197
+ changes:
198
+ commands:
199
+ - get
200
+ - list
201
+ managed-zone:
202
+ commands:
203
+ - create
204
+ - delete
205
+ - get
206
+ - list
207
+ project-info:
208
+ commands:
209
+ - get
210
+ records:
211
+ commands:
212
+ - edit
213
+ - list
@@ -0,0 +1,40 @@
1
+ # coding: utf-8
2
+
3
+ require "milc/gcloud/compute"
4
+
5
+ module Milc
6
+ module Gcloud
7
+ module Compute
8
+ module FirewallRules
9
+ def compare(attrs, res)
10
+ attrs = attrs.dup
11
+ Milc.logger.debug("*" * 100)
12
+ [:allow, :source_ranges, :target_tags].each do |k|
13
+ attrs[k] = split_sort(attrs[k])
14
+ end
15
+ res = res.symbolize_keys
16
+ res[:allow] = res[:allowed].map{|h|
17
+ proto = h["IPProtocol"]
18
+ if ports = h["ports"]
19
+ ports.map{|port| '%s:%s' % [proto, port] }
20
+ else
21
+ [proto]
22
+ end
23
+ }.tap(&:flatten!).sort
24
+ {
25
+ :sourceRanges => :source_ranges,
26
+ :targetTags => :target_tags,
27
+ }.each do |k1, k2|
28
+ res[k2] = res[k1] ? res[k1].sort : nil
29
+ end
30
+ super(attrs, res)
31
+ end
32
+
33
+ def call_update(cmd_args, attrs, &block)
34
+ attrs = attrs.reject{|k,v| k == :network}
35
+ super(cmd_args, attrs, &block)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+
3
+ require "milc/gcloud/compute"
4
+
5
+ require 'active_support/core_ext/array/wrap'
6
+
7
+ module Milc
8
+ module Gcloud
9
+ module Compute
10
+ module Instances
11
+ def build_attr_arg(attr_name, value)
12
+ case attr_name
13
+ when :disk, :disks then
14
+ disks = Array.wrap(value).map{|d| d.is_a?(Hash) ? build_sub_attr_args(d) : d.to_s }
15
+ disks.map{|d| "--disk #{d}"}.join(" ")
16
+ else
17
+ super(attr_name, value)
18
+ end
19
+ end
20
+
21
+ def first_internal_ip(network_interfaces)
22
+ network_interfaces.map{|i| i["networkIP"]}.compact.first
23
+ end
24
+ module_function :first_internal_ip
25
+
26
+ def first_external_ip(network_interfaces)
27
+ network_interfaces.map{|i|
28
+ configs = i["accessConfigs"] || []
29
+ configs.map{|c| c["natIP"] }.compact.first
30
+ }.flatten.first
31
+ end
32
+ module_function :first_external_ip
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ # coding: utf-8
2
+
3
+ require "milc/gcloud/compute"
4
+
5
+ require 'active_support/core_ext/array/wrap'
6
+
7
+ module Milc
8
+ module Gcloud
9
+ module Compute
10
+ module TargetPools
11
+ def add_instances(cmd_args, attrs, &block)
12
+ call_action("add-instances", cmd_args, attrs, &block)
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ # coding: utf-8
2
+
3
+ require "milc/gcloud"
4
+
5
+ module Milc
6
+ module Gcloud
7
+ module Compute
8
+ autoload :FirewallRules, 'milc/gcloud/compute/firewall_rules'
9
+ autoload :Instances , 'milc/gcloud/compute/instances'
10
+ autoload :TargetPools , 'milc/gcloud/compute/target_pools'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ require "milc"
2
+
3
+ module Milc
4
+ module Gcloud
5
+
6
+ class UnsupportedCommandError < StandardError
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,144 @@
1
+ # coding: utf-8
2
+
3
+ require "milc/gcloud"
4
+
5
+ require "yaml"
6
+
7
+ require 'active_support/core_ext/string/inflections'
8
+
9
+ module Milc
10
+ module Gcloud
11
+ class Resource
12
+ class << self
13
+ def command_defs
14
+ @command_defs ||= YAML.load_file(File.expand_path("../commands.yml", __FILE__))
15
+ end
16
+
17
+ def command_def_for(service, resource)
18
+ c = command_defs
19
+ s = c[service] or raise "service #{service.inspect} not found in #{commands.keys.join(', ')}"
20
+ s[resource] or raise "resource #{resource.inspect} not found in #{s.keys.join(' ')} of #{service.inspect}"
21
+ end
22
+
23
+ def lookup(project, service, resource)
24
+ Milc.logger.debug("=" * 100)
25
+ Milc.logger.debug("project: #{project}, service: #{service}, resource: #{resource}")
26
+
27
+ command_def = command_def_for(service, resource)
28
+ result = new(project, service, resource, command_def['commands'])
29
+ service_module = Milc::Gcloud.const_get(service.classify)
30
+ m = resource.gsub(/-/, '_').camelize.to_sym
31
+ if service_module.constants.include?(m)
32
+ resource_module = service_module.const_get(m)
33
+ Milc.logger.debug("#{m} found as #{resource_module.inspect}")
34
+
35
+ result.extend(resource_module)
36
+ else
37
+ Milc.logger.debug("#{m} not found in #{service_module.constants.inspect}")
38
+ end
39
+ result
40
+ end
41
+ end
42
+
43
+ attr_reader :project, :service, :resource, :commands
44
+ def initialize(project, service, resource, commands)
45
+ @project, @service, @resource = project, service, resource
46
+ @commands = commands || []
47
+ end
48
+
49
+ def __gcloud(cmd, &block)
50
+ c = "gcloud #{cmd} --format json"
51
+ c << " --project #{project}" unless c =~ /\s\-\-project[\s\=]/
52
+ res = Gcloud.backend.execute(c, &block)
53
+ res ? JSON.parse(res) : nil
54
+ end
55
+
56
+ def build_attr_arg(attr_name, value)
57
+ "--#{attr_name.to_s.gsub(/\_/, '-')} #{value}"
58
+ end
59
+
60
+ def build_attr_args(attrs)
61
+ attrs.map{|k,v| build_attr_arg(k,v) }.join(" ")
62
+ end
63
+
64
+ def build_sub_attr_args(attrs)
65
+ attrs.map{|k,v| "#{k.to_s.gsub(/\_/, '-')}=#{v}" }.join(" ")
66
+ end
67
+
68
+ def call_action(action, cmd_args, attrs = nil, &block)
69
+ attr_args = attrs.nil? ? '' : build_attr_args(attrs)
70
+ __gcloud("#{service} #{resource} #{action} #{cmd_args} #{attr_args}", &block)
71
+ end
72
+
73
+ def call_update(cmd_args, attrs, &block)
74
+ call_action(:update, cmd_args, attrs, &block)
75
+ end
76
+
77
+ def find(name)
78
+ r = call_action(:list, name)
79
+ r ? r.first : nil
80
+ end
81
+
82
+ def raise_if_invalid(command)
83
+ return if commands.include?(command.to_s)
84
+ raise NotImplementedError, "#{service} #{resource} #{command} is not supported."
85
+ end
86
+
87
+ def normalize_keys(obj)
88
+ case obj
89
+ when Array then obj.map{|o| normalize_keys(o) }
90
+ when Hash then
91
+ obj.each_with_object({}) do |(k,v), d|
92
+ d[k.to_s.underscore.to_sym] = normalize_keys(v)
93
+ end
94
+ else
95
+ obj
96
+ end
97
+ end
98
+
99
+ def compare(attrs, res)
100
+ Milc.logger.debug("compare\n attrs: #{attrs.inspect}\n res: #{res.inspect}")
101
+ res = normalize_keys(res)
102
+ attrs.all?{|k,v| res[k.to_s.gsub(/-/, '_').to_sym] == v }
103
+ end
104
+
105
+ def split_sort(str, spliter = /\s+/, &block)
106
+ return nil unless str
107
+ str.split(spliter).sort(&block)
108
+ end
109
+
110
+ def create(cmd_args, attrs, &block)
111
+ raise_if_invalid(:create)
112
+ name, args = *cmd_args.split(/\s+/, 2)
113
+ r = find(name)
114
+ if r
115
+ return r unless commands.include?('update')
116
+ if compare(attrs, r)
117
+ return r
118
+ else
119
+ return call_update(cmd_args, attrs, &block)
120
+ end
121
+ else
122
+ call_action(:create, cmd_args, attrs, &block)
123
+ end
124
+ end
125
+
126
+ def update(cmd_args, attrs, &block)
127
+ raise_if_invalid(:update)
128
+ name, args = *cmd_args.split(/\s+/, 2)
129
+ r = find(name)
130
+ raise "Resource not found #{service} #{resource} #{name}" unless r
131
+ return r if compare(attrs, r)
132
+ call_update(cmd_args, attrs, &block)
133
+ end
134
+
135
+ def delete(cmd_args, attrs, &block)
136
+ raise_if_invalid(:delete)
137
+ name, args = *cmd_args.split(/\s+/, 2)
138
+ r = find(name)
139
+ return nil unless r
140
+ call_action(:delete, cmd_args, attrs, &block)
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+
3
+ require "milc"
4
+
5
+ require 'active_support/hash_with_indifferent_access'
6
+
7
+ module Milc
8
+ module Gcloud
9
+ autoload :Resource, 'milc/gcloud/resource'
10
+ autoload :Backend , 'milc/gcloud/backend'
11
+
12
+ autoload :Compute , 'milc/gcloud/compute'
13
+ autoload :Sql , 'milc/gcloud/sql'
14
+ autoload :Dns , 'milc/gcloud/dns'
15
+
16
+ autoload :UnsupportedCommandError, 'milc/gcloud/errors'
17
+
18
+ class << self
19
+ def backend
20
+ @backend ||= Milc::Gcloud::Backend::GcloudCommand.new
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ module Milc
2
+ VERSION = "0.1.0"
3
+ end
data/lib/milc.rb ADDED
@@ -0,0 +1,29 @@
1
+ require "milc/version"
2
+
3
+ require 'logger'
4
+
5
+ module Milc
6
+ autoload :Base, 'milc/base'
7
+ autoload :Dsl , 'milc/dsl'
8
+
9
+ autoload :Gcloud, 'milc/gcloud'
10
+
11
+ class << self
12
+ attr_accessor :dry_run
13
+
14
+ attr_reader :verbose
15
+ def verbose=(value)
16
+ @verbose = value
17
+ logger.level = @verbose ? Logger::DEBUG : Logger::INFO
18
+ value
19
+ end
20
+
21
+ def logger
22
+ unless @logger
23
+ @logger = Logger.new($stdout)
24
+ @logger.level = Logger::INFO
25
+ end
26
+ @logger
27
+ end
28
+ end
29
+ end
data/milc.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'milc/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "milc"
8
+ spec.version = Milc::VERSION
9
+ spec.authors = ["akm"]
10
+ spec.email = ["akm2000@gmail.com"]
11
+
12
+ spec.summary = %q{supports gcloud idempotent action of create, update and delete.}
13
+ spec.description = %q{supports gcloud idempotent action of create, update and delete.}
14
+ spec.homepage = "https://github.com/groovenauts/milc"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ if spec.respond_to?(:metadata)
23
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com' to prevent pushes to rubygems.org, or delete to allow pushes to any server."
24
+ end
25
+
26
+ spec.add_runtime_dependency "logger_pipe", "~> 0.2.0"
27
+ spec.add_runtime_dependency "activesupport", "~> 4.2.0"
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.8"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "rspec"
32
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: milc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - akm
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-03-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logger_pipe
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 4.2.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 4.2.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: supports gcloud idempotent action of create, update and delete.
84
+ email:
85
+ - akm2000@gmail.com
86
+ executables:
87
+ - milc
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - ".travis.yml"
94
+ - CODE_OF_CONDUCT.md
95
+ - Gemfile
96
+ - LICENSE.txt
97
+ - README.md
98
+ - Rakefile
99
+ - bin/console
100
+ - bin/setup
101
+ - exe/milc
102
+ - lib/milc.rb
103
+ - lib/milc/base.rb
104
+ - lib/milc/dsl.rb
105
+ - lib/milc/dsl/ansible.rb
106
+ - lib/milc/dsl/gcloud.rb
107
+ - lib/milc/dsl/mgcloud.rb
108
+ - lib/milc/gcloud.rb
109
+ - lib/milc/gcloud/backend.rb
110
+ - lib/milc/gcloud/backend/gcloud_command.rb
111
+ - lib/milc/gcloud/commands.yml
112
+ - lib/milc/gcloud/compute.rb
113
+ - lib/milc/gcloud/compute/firewall_rules.rb
114
+ - lib/milc/gcloud/compute/instances.rb
115
+ - lib/milc/gcloud/compute/target_pools.rb
116
+ - lib/milc/gcloud/errors.rb
117
+ - lib/milc/gcloud/resource.rb
118
+ - lib/milc/version.rb
119
+ - milc.gemspec
120
+ homepage: https://github.com/groovenauts/milc
121
+ licenses:
122
+ - MIT
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 2.4.5
141
+ signing_key:
142
+ specification_version: 4
143
+ summary: supports gcloud idempotent action of create, update and delete.
144
+ test_files: []