rightscale_selfservice 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,72 @@
1
+ # Copyright (c) 2014 Ryan Geyer
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ module RightScaleSelfService
21
+ module Api
22
+ class Resource
23
+ attr_accessor :name
24
+ attr_accessor :service
25
+
26
+ def initialize(name, service)
27
+ @name = name
28
+ @service = service
29
+ end
30
+
31
+ # Finds the specified action and executes it for this resource
32
+ #
33
+ def method_missing(name, *args)
34
+ actions_with_name = @service.client.interface["services"][@service.name][@service.version][@name]["controller"]["actions"].select{|a| a["name"] == name.to_s}
35
+ actions = @service.client.interface["services"][@service.name][@service.version][@name]["controller"]["actions"].map{|a| a["name"]}
36
+ unless actions_with_name.length > 0
37
+ raise "No action named \"#{name}\" was found on resource \"#{@name}\" in version \"#{@service.version}\" of service \"#{@service.name}\". Available actions are [#{actions.join(',')}]"
38
+ end
39
+
40
+ action = actions_with_name.first
41
+ method = action["urls"].first.first.downcase.to_sym
42
+ url = @service.base_url
43
+ url += action["urls"].first.last
44
+ tokens = RightScaleSelfService::Api::Client.get_known_account_id_tokens
45
+ tokens.each do |token|
46
+ url.gsub!(token, @service.client.account_id)
47
+ end
48
+
49
+ params = {:method => method, :url => url, :headers => {"X_API_VERSION" => @service.version}}
50
+ if args.length > 0
51
+ args[0].each do |k,v|
52
+ if url.include? ":#{k}"
53
+ url.gsub!(":#{k}",v)
54
+ args[0].delete(k)
55
+ end
56
+ end
57
+
58
+ if args[0].length > 0
59
+ params[:payload] = URI.encode_www_form(args[0])
60
+ end
61
+ end
62
+
63
+ request = @service.client.get_authorized_rest_client_request(params)
64
+ if args.length > 1 && args[1]
65
+ request
66
+ else
67
+ response = request.execute
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,57 @@
1
+ # Copyright (c) 2014 Ryan Geyer
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ module RightScaleSelfService
21
+ module Api
22
+ # A base class for behavior shared with all SS API Services. Today
23
+ # they are (designer,catalog,manager)
24
+ #
25
+ # @see http://support.rightscale.com/12-Guides/Self-Service
26
+ class Service
27
+ attr_accessor :name
28
+
29
+ attr_accessor :client
30
+
31
+ attr_accessor :version
32
+
33
+ attr_accessor :base_url
34
+
35
+ def initialize(name, version, base_url, client)
36
+ @resources = {}
37
+ @name = name
38
+ @version = version
39
+ @base_url = base_url
40
+ @client = client
41
+ end
42
+
43
+ def method_missing(name, *arguments)
44
+ unless client.interface["services"][@name][@version].has_key?(name.to_s)
45
+ raise "No resource named \"#{name}\" was found in version \"#{@version}\" of service \"#{@name}\". Available resources are [#{client.interface["services"][@name][@version].keys.join(',')}]"
46
+ end
47
+
48
+ if @resources.has_key?(name.to_s)
49
+ @resources[name.to_s]
50
+ else
51
+ resource = RightScaleSelfService::Api::Resource.new(name.to_s, self)
52
+ @resources[name.to_s] = resource
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,52 @@
1
+ # Copyright (c) 2014 Ryan Geyer
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ module RightScaleSelfService
21
+ module Cli
22
+ class Base < Thor
23
+ class_option :auth_hash, :type => :hash, :banner => "<auth-hash>", :desc => "A hash of auth parameters in the form (email:foo@bar.baz password:password account_id:12345)"
24
+ class_option :auth_file, :banner => "<auth-filepath>", :desc => "A yaml file containing auth parameters to use for authentication"
25
+
26
+ no_commands {
27
+ def get_api_client()
28
+ client_auth_params = {}
29
+ thor_shell = Thor::Shell::Color.new
30
+ unless @options.keys.include?('auth_file') | @options.keys.include?('auth_hash')
31
+ message = <<EOF
32
+ You must supply authentication details as either a hash or
33
+ a yaml authentication file!
34
+ EOF
35
+ thor_shell.say(thor_shell.set_color(message, :red))
36
+ exit 1
37
+ end
38
+ if @options['auth_file']
39
+ client_auth_params = YAML.load_file(File.expand_path(@options['auth_file'], Dir.pwd))
40
+ end
41
+
42
+ if @options['auth_hash']
43
+ # Thanks - http://stackoverflow.com/questions/800122/best-way-to-convert-strings-to-symbols-in-hash
44
+ client_auth_params = @options['auth_hash'].inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
45
+ end
46
+
47
+ RightScaleSelfService::Api::Client.new(client_auth_params)
48
+ end
49
+ }
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2014 Ryan Geyer
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ require File.expand_path(File.join(File.dirname(__FILE__), 'template.rb'))
21
+
22
+ module RightScaleSelfService
23
+ module Cli
24
+ class Main < Base
25
+ desc "template", "Self Service Template Commands"
26
+ subcommand "template", Template
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,45 @@
1
+ # Copyright (c) 2014 Ryan Geyer
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ module RightScaleSelfService
21
+ module Cli
22
+ class Template < Base
23
+ desc "preprocess <filepath>", "Processes <filepath>, #include:/path/to/file statements with file contents. Will create a new file in the same location prefixed with 'processed-', or in the location specified by -o"
24
+ option :o, :banner => "<output filepath>"
25
+ def preprocess(filepath)
26
+ source_filepath = File.expand_path(filepath, Dir.pwd)
27
+ source_filename = File.basename(source_filepath)
28
+ source_dir = File.dirname(source_filepath)
29
+ dest_filepath = @options.has_key?('o') ? File.expand_path(@options['o'], Dir.pwd) : File.join(source_dir, "processed-#{source_filename}")
30
+ result = RightScaleSelfService::Utilities::Template.preprocess(source_filepath)
31
+ File.open(dest_filepath, 'w') {|f| f.write(result)}
32
+ end
33
+
34
+ desc "compile <filepath>", "Uploads <filepath> to SS, validating the syntax. Will report errors if any are found."
35
+ def compile(filepath)
36
+ source_filepath = File.expand_path(filepath, Dir.pwd)
37
+ source_filename = File.basename(source_filepath)
38
+ source_dir = File.dirname(source_filepath)
39
+ result = RightScaleSelfService::Utilities::Template.preprocess(source_filepath)
40
+ client = get_api_client()
41
+ client.designer.template.compile(:source => result)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,92 @@
1
+ # Copyright (c) 2014 Ryan Geyer
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ require 'yaml'
21
+
22
+ module RightScaleSelfService
23
+ module Utilities
24
+ class Template
25
+ # Validates that the specified file exists, raising an error if it does not.
26
+ # Then reads the file into a string which is returned
27
+ #
28
+ # @param file [String] the path to the file which should be returned as a string
29
+ #
30
+ # @raise [Errno::ENOENT] If the file does not exist
31
+ # @return [String] the content of the supplied file
32
+ def self.file_to_str_and_validate(file)
33
+ cat_str = File.open(File.expand_path(file), 'r') { |f| f.read }
34
+ end
35
+
36
+ # Returns a de duped hash of files to include by recursively parsing and
37
+ # looking for #include:<relative file path> in the file and all included
38
+ # files.
39
+ #
40
+ # @param file [String] the path of the file to parse for includes
41
+ #
42
+ # @raise [Errno::ENOENT] if the specified file, or any included files do
43
+ # not exist
44
+ #
45
+ # @return [Hash] a de duped hash of include files, where the key is the
46
+ # fully qualified path and filename, and the values are the relative
47
+ # path supplied in the include statement.
48
+ def self.get_include_list(file)
49
+ dedupe_include_list = {}
50
+ contents = file_to_str_and_validate(file)
51
+ contents.scan(/#include:(.*)$/).each do |include|
52
+ include_filepath = File.expand_path(include.first, File.dirname(file))
53
+ dedupe_include_list.merge!({include_filepath => include.first})
54
+ # This merges only the new keys by doing a diff
55
+ child_includes_hash = get_include_list(include_filepath)
56
+ new_keys = child_includes_hash.keys() - dedupe_include_list.keys()
57
+ merge_these = child_includes_hash.select {|k,v| new_keys.include?(k) }
58
+ dedupe_include_list.merge!(merge_these)
59
+ end
60
+ dedupe_include_list
61
+ end
62
+
63
+ def self.preprocess(file)
64
+ parent_template = file_to_str_and_validate(file)
65
+ dedup_include_list = get_include_list(file)
66
+
67
+ dedup_include_list.each do |key,val|
68
+ include_filepath = key
69
+ include_contents = <<EOF
70
+ ###############################################################################
71
+ # BEGIN Include from #{val}
72
+ ###############################################################################
73
+ EOF
74
+
75
+ include_contents += file_to_str_and_validate(key)
76
+
77
+ include_contents += <<EOF
78
+ ###############################################################################
79
+ # END Include from #{val}
80
+ ###############################################################################
81
+ EOF
82
+
83
+ parent_template.sub!("#include:#{val}",include_contents)
84
+ end
85
+ # Clear all include lines from templates which were included from other templates
86
+ parent_template.gsub!(/#include:(.*)$/,"")
87
+ parent_template
88
+ end
89
+
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2014 Ryan Geyer
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ require 'thor'
21
+ require 'logger-better'
22
+ glob_path = File.expand_path(File.join(File.dirname(__FILE__), 'rightscale_selfservice')) + '/**/*.rb'
23
+ Dir.glob(glob_path, &method(:require))
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rightscale_selfservice
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ryan J. Geyer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '0.19'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '0.19'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rest-client
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: logger-better
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '0.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '0.1'
55
+ description: A rubygem with a buncha useful CLI bits for RightScale Self Service,
56
+ including a test harness for Cloud Application Templates
57
+ email: me@ryangeyer.com
58
+ executables:
59
+ - rightscale_selfservice
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - LICENSE
64
+ - README.md
65
+ - bin/rightscale_selfservice
66
+ - lib/rightscale_selfservice.rb
67
+ - lib/rightscale_selfservice/api/client.rb
68
+ - lib/rightscale_selfservice/api/interface.json
69
+ - lib/rightscale_selfservice/api/resource.rb
70
+ - lib/rightscale_selfservice/api/service.rb
71
+ - lib/rightscale_selfservice/cli/base.rb
72
+ - lib/rightscale_selfservice/cli/main.rb
73
+ - lib/rightscale_selfservice/cli/template.rb
74
+ - lib/rightscale_selfservice/utilities/template.rb
75
+ homepage: https://github.com/rgeyer/rightscale_selfservice
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.2.2
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: A rubygem with a buncha useful CLI bits for RightScale Self Service, including
99
+ a test harness for Cloud Application Templates
100
+ test_files: []