right_api_helper 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,25 @@
1
+ spec/cassettes/*
2
+ cache/*
3
+ .DS_Store
4
+ *.gem
5
+ *.rbc
6
+ .bundle
7
+ .config
8
+ .yardoc
9
+ Gemfile.lock
10
+ InstalledFiles
11
+ _yardoc
12
+ coverage
13
+ doc/
14
+ lib/bundler/man
15
+ pkg
16
+ rdoc
17
+ spec/reports
18
+ test/tmp
19
+ test/version_tmp
20
+ tmp
21
+ *.bundle
22
+ *.so
23
+ *.o
24
+ *.a
25
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format nested
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in right_api_helper.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2014 RightScale, Inc.
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # RightApiHelper
2
+
3
+ A collection of helper objects and methods that encapsulate commonly used idioms for [right_api_client](https://github.com/rightscale/right_api_client) users.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'right_api_helper'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install right_api_helper
18
+
19
+ ## Usage
20
+
21
+
22
+ ### Getting a connection
23
+
24
+ Get started by creating a [right_api_client](https://github.com/rightscale/right_api_client) handle:
25
+
26
+ @client = RightApiHelper::Session.new.create_client("someemail", "somepasswd", "someaccountid", "https://my.rightscale.com")
27
+
28
+ or
29
+
30
+ @client = RightApiHelper::Session.new.create_client_from_file("~/.right_api_client/login.yml")
31
+
32
+ ### Using a helper
33
+
34
+ Now pass the client handle to a helper object to use it's methods:
35
+
36
+ deployment_helper = RightApiHelper::Deployments.new(@client)
37
+ my_deployment = @deployment_helper.find_or_create("My Cool Deployment")
38
+
39
+ ### Logging
40
+
41
+ By default the helpers log to STDOUT. But you can modify that by passing a custom `Logger` to each helper. Here is the example from above modified to use a custom logger.
42
+
43
+ my_logger = Logger.new("/tmp/right_api.log)
44
+ deployment_helper = RightApiHelper::Deployments.new(client)
45
+ deployment_helper.logger(my_logger)
46
+ my_deployment = @deployment_helper.find_or_create("My Cool Deployment")
47
+
48
+ You can also pass a logger object to the `right_api_client` gem. For example:
49
+
50
+ session = RightApiHelper::Session.new
51
+ session.logger(my_logger)
52
+ @client = session.create_client_from_file("~/.right_api_client/login.yml")
53
+
54
+
55
+ ## TODO
56
+
57
+ * Need to further sanitize VCR output before including spec/cassettes dir.
58
+ * break `lib/right_api_helper/api15.rb` apart into separate helpers?
59
+
60
+ ## Contributing
61
+
62
+ 1. Fork it ( https://github.com/caryp/right_api_helper/fork )
63
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
64
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
65
+ 4. Push to the branch (`git push origin my-new-feature`)
66
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
data/bin/organize ADDED
@@ -0,0 +1,193 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Author: cary@rightscale.com
4
+ # Copyright 2014 RightScale, Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ # Example:
19
+ # bundle exec bin/organize preview demo/deployments.json --deployment-regexps="ec2:Name=([a-z]+)-([a-z])-([a-z]+)[0-9]+" --name-regexps="ec2:Name=[a-z]+-[a-z]-([a-z]+[0-9]+)"
20
+ #
21
+ # To better view results:
22
+ #
23
+ # > cd demo
24
+ # > ./start_server
25
+ #
26
+ # Then point your browser to http://localhost:8000/
27
+ #
28
+
29
+ require 'rubygems'
30
+ require 'thor'
31
+ require 'right_api_helper'
32
+
33
+ require 'pry'
34
+
35
+ class OrganizeApp < Thor
36
+
37
+ desc "preview FILE", "generate an organization preview and output to JSON file."
38
+ option :deployment_regexps, :required => true
39
+ option :prefix
40
+ option :name_regexps
41
+ option :debug, :type => :boolean
42
+ option :clear_cache, :type => :boolean
43
+ def preview(filename)
44
+ # setup
45
+ setup_logging(options[:debug])
46
+ initialize_api_client
47
+ setup_cache_objects(options[:clear_cache])
48
+
49
+ # organize
50
+ result_hash =
51
+ organize_by_tags(
52
+ get_tag_array(options[:deployment_regexps]),
53
+ get_tag_array(options[:name_regexps]),
54
+ options[:prefix]
55
+ )
56
+
57
+ # write results to a file
58
+ json = JSON.pretty_generate(result_hash)
59
+ @log.debug "JSON: #{json}"
60
+ File.open(filename, "w") { |f| f.write(json)}
61
+ @log.info("Done. Results written to '#{filename}'")
62
+ end
63
+
64
+ private
65
+
66
+ def setup_logging(debug)
67
+ @log = Logger.new(STDOUT)
68
+ @log.formatter = proc do |severity, datetime, progname, msg|
69
+ "#{msg}\n"
70
+ end
71
+ @log.level = Logger::INFO
72
+ @log.level = Logger::DEBUG if debug
73
+ end
74
+
75
+ def initialize_api_client
76
+ session = RightApiHelper::Session.new
77
+ session.logger(@log)
78
+ @client ||= session.create_client_from_file("~/.right_api_client/login.yml")
79
+ end
80
+
81
+ def setup_cache_objects(clear=false)
82
+ @cache_dir = File.join(".", "cache")
83
+ @instance_cache ||= RightApiHelper::Cache.new("instances", @cache_dir)
84
+ @tag_cache ||= RightApiHelper::Cache.new("tags", @cache_dir)
85
+ if clear
86
+ @instance_cache.clear ; @tag_cache.clear
87
+ FileUtils.rmdir(@cache_dir)
88
+ end
89
+ FileUtils.mkdir(@cache_dir) unless File.directory?(@cache_dir)
90
+ end
91
+
92
+ def get_tag_array(option)
93
+ array = []
94
+ array = option.split(",") if option
95
+ array
96
+ end
97
+
98
+ def instance_helper
99
+ @helper ||= RightApiHelper::Instances.new(@client)
100
+ @helper.logger(@log)
101
+ @helper
102
+ end
103
+
104
+ # organize into groups based on tags
105
+ #
106
+ # All instances who's captures match all deployment_regexps will be grouped
107
+ # together. The name of the group can be affected by passing in name_regexps and prefix.
108
+ #
109
+ # Array : deployment_regexps : list of namespace:key=value_regex values
110
+ #
111
+ # Returns: String : JSON object containing instances grouped by deployment_regexps
112
+ def organize_by_tags(deployment_regexps, name_regexps=[], prefix="")
113
+ @log.debug "ORGANIZE PARAMS: deployment_regexps: #{deployment_regexps} name_regexps: #{name_regexps}, prefix: #{prefix}"
114
+ output_hash = {}
115
+
116
+ # cached API queries for instances
117
+ instances_by_href = query_instances
118
+
119
+ # uncached tags query
120
+ instance_hrefs = instances_by_href.keys
121
+ @log.info "Querying tags from RightScale API..."
122
+ @log.debug "instance_hrefs: #{instance_hrefs.inspect}"
123
+ tag_data = @client.tags.by_resource(:resource_hrefs => instance_hrefs)
124
+
125
+ tag_data.each do |tag|
126
+ resources = tag.resource.is_a?(Array) ? tag.resource : [tag.resource]
127
+ resources.each do |resource|
128
+ tags = tag.tags.map{|t| t["name"]}
129
+ href = resource.href
130
+ relevant_tags_key= gather_relevant_tags(deployment_regexps, tags)
131
+ new_name = gather_relevant_tags(name_regexps, tags) if name_regexps
132
+
133
+ unless relevant_tags_key.empty?
134
+ instance_name = (new_name.nil? || new_name.empty?) ? instances_by_href[href] : new_name
135
+ instance_hash = {"href" => href, "type" => "Instance", "name" => instance_name}
136
+ output_hash[relevant_tags_key] ||= {"name" => "#{prefix}#{relevant_tags_key}", "children" => []}
137
+ output_hash[relevant_tags_key]["children"] << instance_hash
138
+ end
139
+ end
140
+ end
141
+ deployments_hash = { "deployments" => [] }
142
+
143
+ output_hash.each do |deployment_type, deployment_data|
144
+ deployments_hash["deployments"] << deployment_data
145
+ end
146
+ deployments_hash
147
+ end
148
+
149
+ # query instance data
150
+ #
151
+ # Use local cachefile to improve performance
152
+ #
153
+ def query_instances
154
+ instances_by_href = {}
155
+ if (instances_by_href = @instance_cache.get) == nil
156
+ @log.info "Querying instances from RightScale API (might take a few minutes)..."
157
+ instances = instance_helper.get_unmanaged_instances
158
+ instances_by_href = instances.inject({}) {|new_hash, instance| instance.show ; new_hash[instance.href] = existing_name(instance); new_hash}
159
+ @instance_cache.set(instances_by_href)
160
+ end
161
+ @log.debug "instances_by_href: #{instances_by_href.inspect}"
162
+ instances_by_href
163
+ end
164
+
165
+ def existing_name(instance)
166
+ if instance.respond_to?(:name)
167
+ instance.name
168
+ elsif instance.respond_to?(:resource_uid)
169
+ instance.resource_uid
170
+ else
171
+ "unknown"
172
+ end
173
+ end
174
+
175
+ def gather_relevant_tags(tag_regexps, tags, delimiter = '-')
176
+ return_tags = []
177
+ tag_regexps.each do |regexp_str|
178
+ regexp = Regexp.new(regexp_str)
179
+ match_data = nil
180
+ tags.detect{|t| match_data = regexp.match(t)}
181
+ return_tags += match_data.captures if match_data
182
+ end
183
+ return_tags.flatten.join(delimiter)
184
+ end
185
+
186
+ def client
187
+ @client ||= RightApi::Client.new(YAML.load_file(File.expand_path('~/.right_api_client/login.yml', __FILE__)))
188
+ end
189
+
190
+ end
191
+
192
+ params = OrganizeApp.start(ARGV)
193
+
@@ -0,0 +1,44 @@
1
+ {
2
+ "deployments": [
3
+ {
4
+ "name": "zensmartfeedpool-b-zookeeper",
5
+ "children": [
6
+ {
7
+ "href": "/api/clouds/3/instances/CFD3EJB1P9L5D",
8
+ "type": "Instance",
9
+ "name": "i-fb8d86a4"
10
+ }
11
+ ]
12
+ },
13
+ {
14
+ "name": "zensmartfeedpool-a-zookeeper",
15
+ "children": [
16
+ {
17
+ "href": "/api/clouds/3/instances/C40BA3BLJ77JF",
18
+ "type": "Instance",
19
+ "name": "i-858d86da"
20
+ },
21
+ {
22
+ "href": "/api/clouds/3/instances/42S13K03IDSDV",
23
+ "type": "Instance",
24
+ "name": "i-808d86df"
25
+ },
26
+ {
27
+ "href": "/api/clouds/3/instances/8BKCHD746OE69",
28
+ "type": "Instance",
29
+ "name": "i-b91912e6"
30
+ }
31
+ ]
32
+ },
33
+ {
34
+ "name": "zensmartfeedpool-a-zook",
35
+ "children": [
36
+ {
37
+ "href": "/api/clouds/3/instances/80J8V6NUU2TOM",
38
+ "type": "Instance",
39
+ "name": "i-d9050e86"
40
+ }
41
+ ]
42
+ }
43
+ ]
44
+ }
data/demo/index.html ADDED
@@ -0,0 +1,83 @@
1
+ <html>
2
+ <style>
3
+
4
+ body {
5
+ min-width: 600px;
6
+ margin:0;
7
+ padding:0;
8
+ font-family:'Lucida Grande','Lucida Sans Unicode','Lucida Sans',Verdana,lucida,sans-serif;
9
+ background:#FFF;
10
+ height:100%
11
+ }
12
+
13
+ .banner {
14
+ background:#235186;
15
+ padding: 10;
16
+ }
17
+
18
+ .logo {
19
+ padding: 3 20 10;
20
+
21
+ float: left;
22
+ height:30px;
23
+ }
24
+
25
+ .bucket_name {
26
+ padding: 0 20 10;
27
+
28
+ font-size: 19px;
29
+ color: #F5F0A9;
30
+ background:#235186;
31
+ }
32
+
33
+
34
+ .disclaimer {
35
+ background: #FFFFFF;
36
+ margin-left: auto;
37
+ margin-right: auto;
38
+ position: relative;
39
+ color: black;
40
+ border: 2px solid black;
41
+ font-weight: normal;
42
+ font-size: 14px;
43
+ padding: 2px 20px;
44
+ position: relative;
45
+ clear: both;
46
+ }
47
+
48
+ .jqtree_common, h1, h2, h3 {
49
+ color: #235186;
50
+ background:#F5F2A9;
51
+ padding: 3;
52
+ margin: 0;
53
+ text-indent: 10;
54
+ }
55
+ .jqtree-title {
56
+ font-size: 16px;
57
+ }
58
+
59
+
60
+
61
+ </style>
62
+ <head>
63
+ <title>jQuery test</title>
64
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
65
+ <script src="tree.jquery.js"></script>
66
+
67
+ <script type="text/javascript">
68
+ $(function() {
69
+ $.getJSON(
70
+ 'deployments.json',
71
+ function(result) {
72
+ $('#tree1').tree({ data: result.deployments });
73
+ });
74
+ });
75
+ </script>
76
+ </head>
77
+ <div class='banner'>
78
+ <div class='logo'><img alt='Embedded Image' width='140' height='19' src='logo.png' /></div>
79
+ <div class='bucket_name'>Instance Organize Preview</div>
80
+
81
+ </div>
82
+ <div id="tree1" data-url="."></div>
83
+ </html>
data/demo/logo.png ADDED
Binary file
@@ -0,0 +1,12 @@
1
+ #!/bin/bash
2
+ #
3
+ # Run a local http server from this directory on port 8000
4
+ #
5
+ PORT=8000
6
+
7
+ if [ -z `which python` ]; then
8
+ echo "FATAL: python must be installed"
9
+ exit 1
10
+ fi
11
+
12
+ python -m SimpleHTTPServer $PORT