right_api_helper 0.0.1

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.
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