vermillion-client 1.0.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.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.hound.yml +2 -0
  4. data/.rubocop.yml +320 -0
  5. data/Gemfile +3 -0
  6. data/Gemfile.lock +26 -0
  7. data/README.md +55 -0
  8. data/Rakefile +10 -0
  9. data/bin/setup +7 -0
  10. data/bin/vermillion +16 -0
  11. data/doc/ChangeBranchTest.html +240 -0
  12. data/doc/ConfigurationTest.html +277 -0
  13. data/doc/CreateTest.html +240 -0
  14. data/doc/Gemfile.html +145 -0
  15. data/doc/Gemfile_lock.html +173 -0
  16. data/doc/README_md.html +216 -0
  17. data/doc/Rakefile.html +151 -0
  18. data/doc/UpdateTest.html +280 -0
  19. data/doc/Vermillion.html +272 -0
  20. data/doc/Vermillion/Cfg.html +362 -0
  21. data/doc/Vermillion/Controller.html +185 -0
  22. data/doc/Vermillion/Controller/Base.html +503 -0
  23. data/doc/Vermillion/Controller/Change.html +301 -0
  24. data/doc/Vermillion/Controller/Create.html +301 -0
  25. data/doc/Vermillion/Controller/Firstrun.html +256 -0
  26. data/doc/Vermillion/Controller/Status.html +308 -0
  27. data/doc/Vermillion/Controller/Update.html +326 -0
  28. data/doc/Vermillion/Helper.html +252 -0
  29. data/doc/Vermillion/Helper/ApiCommunication.html +307 -0
  30. data/doc/Vermillion/Helper/Endpoint.html +506 -0
  31. data/doc/Vermillion/Helper/Formatting.html +250 -0
  32. data/doc/Vermillion/Helper/Network.html +304 -0
  33. data/doc/Vermillion/Helper/Results.html +341 -0
  34. data/doc/Vermillion/Helper/Time.html +295 -0
  35. data/doc/Vermillion/Request.html +332 -0
  36. data/doc/Vermillion/Router.html +351 -0
  37. data/doc/Vermillion/Test.html +183 -0
  38. data/doc/Vermillion/Test/Base.html +260 -0
  39. data/doc/Vermillion/Utils.html +247 -0
  40. data/doc/bin/setup.html +147 -0
  41. data/doc/created.rid +33 -0
  42. data/doc/images/add.png +0 -0
  43. data/doc/images/arrow_up.png +0 -0
  44. data/doc/images/brick.png +0 -0
  45. data/doc/images/brick_link.png +0 -0
  46. data/doc/images/bug.png +0 -0
  47. data/doc/images/bullet_black.png +0 -0
  48. data/doc/images/bullet_toggle_minus.png +0 -0
  49. data/doc/images/bullet_toggle_plus.png +0 -0
  50. data/doc/images/date.png +0 -0
  51. data/doc/images/delete.png +0 -0
  52. data/doc/images/find.png +0 -0
  53. data/doc/images/loadingAnimation.gif +0 -0
  54. data/doc/images/macFFBgHack.png +0 -0
  55. data/doc/images/package.png +0 -0
  56. data/doc/images/page_green.png +0 -0
  57. data/doc/images/page_white_text.png +0 -0
  58. data/doc/images/page_white_width.png +0 -0
  59. data/doc/images/plugin.png +0 -0
  60. data/doc/images/ruby.png +0 -0
  61. data/doc/images/tag_blue.png +0 -0
  62. data/doc/images/tag_green.png +0 -0
  63. data/doc/images/transparent.png +0 -0
  64. data/doc/images/wrench.png +0 -0
  65. data/doc/images/wrench_orange.png +0 -0
  66. data/doc/images/zoom.png +0 -0
  67. data/doc/index.html +138 -0
  68. data/doc/js/darkfish.js +155 -0
  69. data/doc/js/jquery.js +4 -0
  70. data/doc/js/navigation.js +142 -0
  71. data/doc/js/search.js +94 -0
  72. data/doc/js/search_index.js +1 -0
  73. data/doc/js/searcher.js +228 -0
  74. data/doc/rdoc.css +595 -0
  75. data/doc/table_of_contents.html +255 -0
  76. data/doc/vermillion-client_gemspec.html +166 -0
  77. data/lib/client.rb +35 -0
  78. data/lib/client/config.rb +58 -0
  79. data/lib/client/controller.rb +68 -0
  80. data/lib/client/controller/change.rb +26 -0
  81. data/lib/client/controller/create.rb +26 -0
  82. data/lib/client/controller/firstrun.rb +30 -0
  83. data/lib/client/controller/status.rb +43 -0
  84. data/lib/client/controller/update.rb +26 -0
  85. data/lib/client/helper.rb +21 -0
  86. data/lib/client/helper/apicommunication.rb +78 -0
  87. data/lib/client/helper/endpoint.rb +61 -0
  88. data/lib/client/helper/formatting.rb +23 -0
  89. data/lib/client/helper/network.rb +54 -0
  90. data/lib/client/helper/results.rb +28 -0
  91. data/lib/client/helper/time.rb +33 -0
  92. data/lib/client/request.rb +22 -0
  93. data/lib/client/router.rb +56 -0
  94. data/lib/client/utils.rb +18 -0
  95. data/lib/client/version.rb +4 -0
  96. data/lib/test.rb +13 -0
  97. data/lib/test/base.rb +17 -0
  98. data/test/test_change_branch.rb +14 -0
  99. data/test/test_configuration.rb +21 -0
  100. data/test/test_create.rb +14 -0
  101. data/test/test_update.rb +24 -0
  102. data/vermillion-client.gemspec +23 -0
  103. metadata +201 -0
@@ -0,0 +1,58 @@
1
+ module Vermillion
2
+ # Flag for enabling more verbose output from certain methods
3
+ DEBUG = false
4
+
5
+ class Cfg
6
+ # Perform first run tasks and create or read config file values
7
+ def bootstrap!
8
+ populate_config
9
+
10
+ return if valid_config?
11
+
12
+ # no config file found, lets create one using the firstrun controller
13
+ require 'client/controller/firstrun'
14
+
15
+ controller = Vermillion::Controller::Firstrun.new
16
+ controller.default
17
+
18
+ populate_config
19
+ end
20
+
21
+ # Returns a hash of all module constants and their values
22
+ def options
23
+ keys = Vermillion.constants.select { |name| constant?(name) }
24
+ hash = {}
25
+
26
+ keys.each { |key| hash[key] = Vermillion.const_get(key) }
27
+ hash
28
+ end
29
+
30
+ # Populates the internal hash which stores any values set in the config file
31
+ def populate_config
32
+ file = File.expand_path("~/.vermillion.yml")
33
+ fmt = Vermillion::Helper.load('formatting')
34
+
35
+ @yml = fmt.symbolize(::YAML.load_file(file))
36
+ self
37
+ end
38
+
39
+ # Get a specific value from the config file data
40
+ # Params:
41
+ # +name+:: String/symbol key value
42
+ def get(name)
43
+ @yml[name.to_sym]
44
+ end
45
+
46
+ private
47
+
48
+ # Check if configuration data exists
49
+ def valid_config?
50
+ !@yml.nil?
51
+ end
52
+
53
+ # Checks if string is a constant
54
+ def constant?(name)
55
+ name == name.upcase
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,68 @@
1
+ module Vermillion
2
+ module Controller
3
+ class Base
4
+ attr_accessor :config, :request
5
+
6
+ # Exit code to indicate everything is ok!
7
+ OK = 0
8
+ # Exit code to indicate a force quit (exit) call, meaning the program
9
+ # quit with an error
10
+ QUIT = 1
11
+ # Exit code to indicate that the program exited with a non-zero exit code,
12
+ # but not one that resulted in a force quit
13
+ QUIT_SOFT = 2
14
+
15
+ # Setup internal variables that will be used in subclasses
16
+ # Params:
17
+ # +config+:: Instance of Vermillion::Cfg to enable access to config file
18
+ # +request+:: Instance of Vermillion::Request, enables access to request
19
+ # parameters
20
+ def initialize(config, request)
21
+ @config = config
22
+ @request = request
23
+
24
+ pre_exec
25
+ end
26
+
27
+ # Perform pre-run tasks
28
+ def pre_exec
29
+ @format = Vermillion::Helper.load('formatting')
30
+ @network = Vermillion::Helper.load('network')
31
+ @network.config = @config
32
+ end
33
+
34
+ # Handle the request
35
+ def exec
36
+ if @request.param.nil?
37
+ send(@method.to_sym)
38
+ else
39
+ send(@method.to_sym, @request.param)
40
+ end
41
+ end
42
+
43
+ # Perform post-run cleanup tasks, such as deleting old logs
44
+ def post_exec
45
+ end
46
+
47
+ # Determines if the command can execute
48
+ # Params:
49
+ # +command+:: Symbol containing the command we want to execute
50
+ def can_exec?(command)
51
+ # no command was passed, check if controller has a default method
52
+ if command.nil? && respond_to?(:default)
53
+ @method = :default
54
+ elsif respond_to? command
55
+ # check the controller for the requested method
56
+ @method = command
57
+ else
58
+ raise NoMethodError, "Invalid method: #{command}"
59
+ end
60
+ end
61
+
62
+ # Default method called by exec if no argument is passed
63
+ def sample
64
+ Notify.warning("Method not implemented")
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,26 @@
1
+ module Vermillion
2
+ module Controller
3
+ class Change < Controller::Base
4
+ include Helper::ApiCommunication
5
+
6
+ # Prepare to execute the requested method
7
+ def pre_exec
8
+ OptionParser.new do |opt|
9
+ opt.banner = "vermillion change [...-flags]"
10
+
11
+ opt.on("-t", "--to=TO", "Branch to change to") { |o| @to = o }
12
+ end.parse!
13
+
14
+ super
15
+ end
16
+
17
+ # Change branches on the selected server
18
+ # +server+:: Symbol representing the server you want to access
19
+ # +to+:: Optional symbol, what branch should we change to?
20
+ def branch(server, to = nil)
21
+ @to = to || @to
22
+ send_to_one(server, :change_branch, to: @to)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Vermillion
2
+ module Controller
3
+ class Create < Controller::Base
4
+ include Helper::ApiCommunication
5
+
6
+ # Prepare to execute the requested method
7
+ def pre_exec
8
+ OptionParser.new do |opt|
9
+ opt.banner = "vermillion create [...-flags]"
10
+
11
+ opt.on("-n", "--name=NAME", "Directory to be created") { |o| @name = o }
12
+ end.parse!
13
+
14
+ super
15
+ end
16
+
17
+ # Create a new project on the requested server
18
+ # +server+:: Symbol representing the server you want to access
19
+ # +name+:: Optional symbol, the name of the project
20
+ def one(server, name = nil)
21
+ @name = name || @name
22
+ send_to_one(server, :create, name: @name)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ module Vermillion
2
+ module Controller
3
+ class Firstrun < Controller::Base
4
+ # Create the configuration file if it does not exist
5
+ def default
6
+ if File.exist?(Dir.home + '/.vermillion.yml')
7
+ Notify.error("Configuration already exists, this is not the first run! Exiting.", show_time: false)
8
+ end
9
+
10
+ File.open(Dir.home + '/.vermillion.yml', "w") do |f|
11
+ f.write <<-'CONTENTS'
12
+ servers:
13
+ -
14
+ name: dev
15
+ address: 192.168.0.74
16
+ https: false
17
+ key: EDIT_ME
18
+ -
19
+ name: local
20
+ address: localhost:8000
21
+ https: false
22
+ key: EDIT_ME
23
+ user:
24
+ test@example.com
25
+ CONTENTS
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,43 @@
1
+ module Vermillion
2
+ module Controller
3
+ class Status < Controller::Base
4
+ # Prints both configuration and server information, returns status code 0
5
+ def default
6
+ print_config
7
+ print_servers
8
+
9
+ OK
10
+ end
11
+
12
+ # Print configuration information
13
+ def config
14
+ print_config
15
+ end
16
+
17
+ # Print configured server information
18
+ def servers
19
+ print_servers
20
+ end
21
+
22
+ private
23
+
24
+ # Process and print config values
25
+ def print_config
26
+ Notify.info("Configuration values")
27
+
28
+ @config.options.each_pair do |key, value|
29
+ Notify.spit " - #{key}: #{value}"
30
+ end
31
+ end
32
+
33
+ # Process and print server values
34
+ def print_servers
35
+ Notify.info('Sites')
36
+
37
+ @config.get(:servers).each do |server|
38
+ Notify.spit(" - Name: #{server[:name]}, Address: #{server[:address]}, HTTPS: #{server[:https]}")
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,26 @@
1
+ module Vermillion
2
+ module Controller
3
+ class Update < Controller::Base
4
+ include Helper::ApiCommunication
5
+
6
+ # Update all sites in the manifest
7
+ def all
8
+ send_to_all(:update)
9
+ end
10
+
11
+ # Update just one server
12
+ # Params:
13
+ # +server+:: Symbol representing the server you want to update
14
+ def one(server)
15
+ send_to_one(server, :update)
16
+ end
17
+
18
+ # Update the configuration manifest for one server
19
+ # Params:
20
+ # +server+:: Symbol representing the server you want to update
21
+ def config(server)
22
+ send_to_one(server, :update_config)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ module Vermillion
2
+ module Helper
3
+ # Loads a helper class
4
+ # Params:
5
+ # +klass+:: String representing the class helper subclass you want to load
6
+ # +args+:: Optional arguments to pass to the class instance
7
+ def self.load(klass, args = nil)
8
+ klass_instance = Vermillion::Helper.const_get(klass.capitalize)
9
+
10
+ if klass_instance
11
+ if args.nil?
12
+ klass_instance.new
13
+ else
14
+ klass_instance.new(args)
15
+ end
16
+ else
17
+ Notify.error("Class not found: #{klass.capitalize}")
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,78 @@
1
+ module Vermillion
2
+ module Helper
3
+ module ApiCommunication
4
+ # Send an HTTP request to one server
5
+ # Params:
6
+ # +input+:: The server you want to connect to
7
+ # +endpoint+:: The REST endpoint you'd like to send a request to
8
+ # +args+:: Any specific configuration data to send along with the request
9
+ def send_to_one(input, endpoint, args = {})
10
+ server, endpoint = setup(input, endpoint, args)
11
+
12
+ begin
13
+ resp = @network.post(endpoint.to_s, server[:key])
14
+
15
+ Notify.spit(endpoint.to_s) if DEBUG
16
+ Notify.spit(resp.body) if DEBUG
17
+
18
+ # generic failure for invalid response type
19
+ raise Errno::ECONNREFUSED if resp["Content-Type"] != "application/json"
20
+
21
+ # handle JSON response
22
+ response_data = @format.symbolize(JSON.parse(resp.body))
23
+
24
+ if response_data[:_code] == 200
25
+ Notify.success("#{server[:name]} (#{server[:address]}) update succeeded")
26
+ elsif !response_data[:message].nil?
27
+ # work around a messaging issue with vermillion-server
28
+ Notify.warning("Error: #{response_data[:message]}")
29
+ else
30
+ Notify.warning("#{response_data[:_title]}: #{response_data[:_message]}")
31
+ end
32
+ rescue Errno::ECONNREFUSED
33
+ Notify.warning("Request failed for #{server[:name]} (#{server[:address]})")
34
+ end
35
+ end
36
+
37
+ # Send HTTP requests to all servers in the local manifest
38
+ # Params:
39
+ # +endpoint+:: The REST endpoint you'd like to send a request to
40
+ # +args+:: Any specific configuration data to send along with the request
41
+ def send_to_all(endpoint, args = {})
42
+ @config.get(:servers).each do |server|
43
+ send_to_one(server[:name], endpoint, args) if server[:name]
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ # Perform setup tasks in ApiCommuniction.send_to_one
50
+ # Params:
51
+ # +input+:: The server you want to connect to
52
+ # +endpoint+:: The REST endpoint you'd like to send a request to
53
+ # +args+:: Any specific configuration data to send along with the request
54
+ def setup(input, endpoint, args = {})
55
+ server_name = input
56
+ remote_site = nil
57
+ server_name, remote_site = input.split('/') if input.to_s.include?('/')
58
+
59
+ server = @config.get(:servers).select { |hash| hash[:name].to_sym == server_name.to_sym }.first
60
+
61
+ # warn user if the server is not defined
62
+ return Notify.warning("Server not found: #{server_name}") unless server
63
+ # warn user if the site does not have a secret key property set
64
+ return Notify.warning("The server configuration must contain a key property to send requests") unless server[:key]
65
+ # warn user if the user key is not defined
66
+ return Notify.warning("The configuration file must contain a user") unless @config.get(:user)
67
+
68
+ endpoint = Endpoint.new("/api/#{endpoint}/")
69
+ endpoint.server = server[:address]
70
+ endpoint.protocol = server[:https]
71
+ endpoint.add(:remote, remote_site) if remote_site
72
+ endpoint.add(:query_string, Utils.to_query_string(args))
73
+
74
+ [server, endpoint]
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,61 @@
1
+ module Vermillion
2
+ module Helper
3
+ class Endpoint
4
+ attr_writer :server
5
+
6
+ # Creates the Endpoint object with default values for internal variables
7
+ # Params:
8
+ # +initial_path+:: Starting point of the URL this class will build
9
+ def initialize(initial_path)
10
+ @path = { default: initial_path }
11
+ @server = nil
12
+ @protocol = "http://"
13
+ end
14
+
15
+ # Set endpoint protocol
16
+ # Params:
17
+ # +use_https+:: Boolean value for whether to use HTTPS
18
+ def protocol=(use_https)
19
+ @protocol = 'https://' if use_https
20
+ end
21
+
22
+ # Add a section to the path
23
+ # Params:
24
+ # +key+:: Symbol, the key to identify the section
25
+ # +value+:: Any value to store with the associated key
26
+ def add(key, value)
27
+ @path[key.to_sym] = value
28
+ end
29
+
30
+ # Return a value based on the provided key
31
+ # Params:
32
+ # +key+:: Symbol, the key to identify the section
33
+ def get(key)
34
+ @path[key.to_sym]
35
+ end
36
+
37
+ # Deletes a value from the internal hash based on a key
38
+ # Params:
39
+ # +key+:: Symbol, the key to identify the section
40
+ def delete(key)
41
+ @path.delete(key)
42
+ end
43
+
44
+ # Checks whether a key exists
45
+ # Params:
46
+ # +key+:: Symbol, the key to identify the section
47
+ def exists?(key)
48
+ @path.key? key
49
+ end
50
+
51
+ # Override the to_s method to return an endpoint fragment
52
+ def to_s
53
+ output = @protocol + @server
54
+ @path.each_pair do |_k, value|
55
+ output += value
56
+ end
57
+ output
58
+ end
59
+ end
60
+ end
61
+ end