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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.hound.yml +2 -0
- data/.rubocop.yml +320 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +26 -0
- data/README.md +55 -0
- data/Rakefile +10 -0
- data/bin/setup +7 -0
- data/bin/vermillion +16 -0
- data/doc/ChangeBranchTest.html +240 -0
- data/doc/ConfigurationTest.html +277 -0
- data/doc/CreateTest.html +240 -0
- data/doc/Gemfile.html +145 -0
- data/doc/Gemfile_lock.html +173 -0
- data/doc/README_md.html +216 -0
- data/doc/Rakefile.html +151 -0
- data/doc/UpdateTest.html +280 -0
- data/doc/Vermillion.html +272 -0
- data/doc/Vermillion/Cfg.html +362 -0
- data/doc/Vermillion/Controller.html +185 -0
- data/doc/Vermillion/Controller/Base.html +503 -0
- data/doc/Vermillion/Controller/Change.html +301 -0
- data/doc/Vermillion/Controller/Create.html +301 -0
- data/doc/Vermillion/Controller/Firstrun.html +256 -0
- data/doc/Vermillion/Controller/Status.html +308 -0
- data/doc/Vermillion/Controller/Update.html +326 -0
- data/doc/Vermillion/Helper.html +252 -0
- data/doc/Vermillion/Helper/ApiCommunication.html +307 -0
- data/doc/Vermillion/Helper/Endpoint.html +506 -0
- data/doc/Vermillion/Helper/Formatting.html +250 -0
- data/doc/Vermillion/Helper/Network.html +304 -0
- data/doc/Vermillion/Helper/Results.html +341 -0
- data/doc/Vermillion/Helper/Time.html +295 -0
- data/doc/Vermillion/Request.html +332 -0
- data/doc/Vermillion/Router.html +351 -0
- data/doc/Vermillion/Test.html +183 -0
- data/doc/Vermillion/Test/Base.html +260 -0
- data/doc/Vermillion/Utils.html +247 -0
- data/doc/bin/setup.html +147 -0
- data/doc/created.rid +33 -0
- data/doc/images/add.png +0 -0
- data/doc/images/arrow_up.png +0 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/delete.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_blue.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/transparent.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +138 -0
- data/doc/js/darkfish.js +155 -0
- data/doc/js/jquery.js +4 -0
- data/doc/js/navigation.js +142 -0
- data/doc/js/search.js +94 -0
- data/doc/js/search_index.js +1 -0
- data/doc/js/searcher.js +228 -0
- data/doc/rdoc.css +595 -0
- data/doc/table_of_contents.html +255 -0
- data/doc/vermillion-client_gemspec.html +166 -0
- data/lib/client.rb +35 -0
- data/lib/client/config.rb +58 -0
- data/lib/client/controller.rb +68 -0
- data/lib/client/controller/change.rb +26 -0
- data/lib/client/controller/create.rb +26 -0
- data/lib/client/controller/firstrun.rb +30 -0
- data/lib/client/controller/status.rb +43 -0
- data/lib/client/controller/update.rb +26 -0
- data/lib/client/helper.rb +21 -0
- data/lib/client/helper/apicommunication.rb +78 -0
- data/lib/client/helper/endpoint.rb +61 -0
- data/lib/client/helper/formatting.rb +23 -0
- data/lib/client/helper/network.rb +54 -0
- data/lib/client/helper/results.rb +28 -0
- data/lib/client/helper/time.rb +33 -0
- data/lib/client/request.rb +22 -0
- data/lib/client/router.rb +56 -0
- data/lib/client/utils.rb +18 -0
- data/lib/client/version.rb +4 -0
- data/lib/test.rb +13 -0
- data/lib/test/base.rb +17 -0
- data/test/test_change_branch.rb +14 -0
- data/test/test_configuration.rb +21 -0
- data/test/test_create.rb +14 -0
- data/test/test_update.rb +24 -0
- data/vermillion-client.gemspec +23 -0
- 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
|