dtk-shell 0.10.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/Gemfile +5 -0
- data/Gemfile_dev +13 -0
- data/README.md +121 -0
- data/bin/dtk-execute +32 -0
- data/bin/dtk-run +92 -0
- data/bin/dtk-shell +31 -0
- data/dtk-shell.gemspec +50 -0
- data/lib/auxiliary.rb +61 -0
- data/lib/bundler_monkey_patch.rb +26 -0
- data/lib/client.rb +58 -0
- data/lib/command_helper.rb +33 -0
- data/lib/command_helpers/git_repo.rb +589 -0
- data/lib/command_helpers/git_repo/merge.rb +153 -0
- data/lib/command_helpers/jenkins_client.rb +106 -0
- data/lib/command_helpers/jenkins_client/config_xml.rb +288 -0
- data/lib/command_helpers/service_importer.rb +251 -0
- data/lib/command_helpers/service_link.rb +33 -0
- data/lib/command_helpers/test_module_creator.rb +69 -0
- data/lib/command_helpers/test_module_templates/dtk.model.yaml.eruby +10 -0
- data/lib/command_helpers/test_module_templates/spec_helper.rb.eruby +10 -0
- data/lib/command_helpers/test_module_templates/temp_component_spec.rb.eruby +5 -0
- data/lib/commands.rb +57 -0
- data/lib/commands/common/thor/access_control.rb +133 -0
- data/lib/commands/common/thor/action_result_handler.rb +74 -0
- data/lib/commands/common/thor/assembly_template.rb +92 -0
- data/lib/commands/common/thor/assembly_workspace.rb +1801 -0
- data/lib/commands/common/thor/base_command_helper.rb +59 -0
- data/lib/commands/common/thor/clone.rb +82 -0
- data/lib/commands/common/thor/common.rb +88 -0
- data/lib/commands/common/thor/common_base.rb +49 -0
- data/lib/commands/common/thor/create_target.rb +70 -0
- data/lib/commands/common/thor/edit.rb +255 -0
- data/lib/commands/common/thor/inventory_parser.rb +98 -0
- data/lib/commands/common/thor/list_diffs.rb +128 -0
- data/lib/commands/common/thor/module.rb +1011 -0
- data/lib/commands/common/thor/module/import.rb +210 -0
- data/lib/commands/common/thor/node.rb +53 -0
- data/lib/commands/common/thor/poller.rb +65 -0
- data/lib/commands/common/thor/pull_clone_changes.rb +28 -0
- data/lib/commands/common/thor/pull_from_remote.rb +152 -0
- data/lib/commands/common/thor/puppet_forge.rb +72 -0
- data/lib/commands/common/thor/purge_clone.rb +101 -0
- data/lib/commands/common/thor/push_clone_changes.rb +162 -0
- data/lib/commands/common/thor/push_to_remote.rb +94 -0
- data/lib/commands/common/thor/remotes.rb +71 -0
- data/lib/commands/common/thor/reparse.rb +40 -0
- data/lib/commands/common/thor/set_required_attributes.rb +46 -0
- data/lib/commands/thor/account.rb +239 -0
- data/lib/commands/thor/assembly.rb +356 -0
- data/lib/commands/thor/attribute.rb +79 -0
- data/lib/commands/thor/component.rb +70 -0
- data/lib/commands/thor/component_module.rb +501 -0
- data/lib/commands/thor/component_template.rb +174 -0
- data/lib/commands/thor/dependency.rb +34 -0
- data/lib/commands/thor/developer.rb +144 -0
- data/lib/commands/thor/dtk.rb +152 -0
- data/lib/commands/thor/library.rb +125 -0
- data/lib/commands/thor/node.rb +504 -0
- data/lib/commands/thor/node_template.rb +94 -0
- data/lib/commands/thor/project.rb +34 -0
- data/lib/commands/thor/provider.rb +233 -0
- data/lib/commands/thor/remotes.rb +49 -0
- data/lib/commands/thor/service.rb +941 -0
- data/lib/commands/thor/service_module.rb +914 -0
- data/lib/commands/thor/state_change.rb +25 -0
- data/lib/commands/thor/target.rb +250 -0
- data/lib/commands/thor/task.rb +116 -0
- data/lib/commands/thor/test_module.rb +310 -0
- data/lib/commands/thor/utils.rb +21 -0
- data/lib/commands/thor/workspace.rb +685 -0
- data/lib/config/cacert.pem +3785 -0
- data/lib/config/client.conf.header +20 -0
- data/lib/config/configuration.rb +99 -0
- data/lib/config/default.conf +16 -0
- data/lib/config/disk_cacher.rb +80 -0
- data/lib/configurator.rb +176 -0
- data/lib/context_router.rb +44 -0
- data/lib/core.rb +497 -0
- data/lib/domain/git_adapter.rb +412 -0
- data/lib/domain/git_error_handler.rb +64 -0
- data/lib/domain/response.rb +285 -0
- data/lib/domain/response/error_handler.rb +86 -0
- data/lib/dtk-shell/version.rb +20 -0
- data/lib/dtk_constants.rb +40 -0
- data/lib/dtk_error.rb +114 -0
- data/lib/dtk_logger.rb +126 -0
- data/lib/dtk_shell.rb +31 -0
- data/lib/error.rb +85 -0
- data/lib/execute.rb +29 -0
- data/lib/execute/cli_pure/cli_rerouter.rb +102 -0
- data/lib/execute/command.rb +40 -0
- data/lib/execute/command/api_call.rb +60 -0
- data/lib/execute/command/api_call/map.rb +60 -0
- data/lib/execute/command/api_call/service.rb +91 -0
- data/lib/execute/command/api_call/translation_term.rb +119 -0
- data/lib/execute/command/rest_call.rb +37 -0
- data/lib/execute/command_processor.rb +30 -0
- data/lib/execute/command_processor/rest_call.rb +59 -0
- data/lib/execute/error_usage.rb +21 -0
- data/lib/execute/execute_context.rb +86 -0
- data/lib/execute/execute_context/result_store.rb +37 -0
- data/lib/execute/script.rb +64 -0
- data/lib/execute/script/add_tenant.rb +121 -0
- data/lib/git-logs/git.log +0 -0
- data/lib/parser/adapters/option_parser.rb +70 -0
- data/lib/parser/adapters/thor.rb +555 -0
- data/lib/parser/adapters/thor/common_option_defs.rb +40 -0
- data/lib/require_first.rb +104 -0
- data/lib/search_hash.rb +44 -0
- data/lib/shell.rb +261 -0
- data/lib/shell/context.rb +1065 -0
- data/lib/shell/context_aux.rb +46 -0
- data/lib/shell/domain/active_context.rb +186 -0
- data/lib/shell/domain/context_entity.rb +89 -0
- data/lib/shell/domain/context_params.rb +223 -0
- data/lib/shell/domain/override_tasks.rb +88 -0
- data/lib/shell/domain/shadow_entity.rb +76 -0
- data/lib/shell/header_shell.rb +44 -0
- data/lib/shell/help_monkey_patch.rb +283 -0
- data/lib/shell/interactive_wizard.rb +225 -0
- data/lib/shell/message_queue.rb +63 -0
- data/lib/shell/parse_monkey_patch.rb +39 -0
- data/lib/shell/status_monitor.rb +124 -0
- data/lib/task_status.rb +83 -0
- data/lib/task_status/refresh_mode.rb +77 -0
- data/lib/task_status/snapshot_mode.rb +28 -0
- data/lib/task_status/stream_mode.rb +48 -0
- data/lib/task_status/stream_mode/element.rb +101 -0
- data/lib/task_status/stream_mode/element/format.rb +101 -0
- data/lib/task_status/stream_mode/element/hierarchical_task.rb +100 -0
- data/lib/task_status/stream_mode/element/hierarchical_task/result.rb +72 -0
- data/lib/task_status/stream_mode/element/hierarchical_task/result/action.rb +93 -0
- data/lib/task_status/stream_mode/element/hierarchical_task/result/components.rb +26 -0
- data/lib/task_status/stream_mode/element/hierarchical_task/result/node_level.rb +26 -0
- data/lib/task_status/stream_mode/element/hierarchical_task/steps.rb +34 -0
- data/lib/task_status/stream_mode/element/hierarchical_task/steps/action.rb +53 -0
- data/lib/task_status/stream_mode/element/hierarchical_task/steps/components.rb +53 -0
- data/lib/task_status/stream_mode/element/hierarchical_task/steps/node_level.rb +42 -0
- data/lib/task_status/stream_mode/element/no_results.rb +26 -0
- data/lib/task_status/stream_mode/element/render.rb +59 -0
- data/lib/task_status/stream_mode/element/stage.rb +84 -0
- data/lib/task_status/stream_mode/element/stage/render.rb +76 -0
- data/lib/task_status/stream_mode/element/task_end.rb +35 -0
- data/lib/task_status/stream_mode/element/task_start.rb +37 -0
- data/lib/util/common_util.rb +37 -0
- data/lib/util/console.rb +235 -0
- data/lib/util/dtk_puppet.rb +65 -0
- data/lib/util/module_util.rb +66 -0
- data/lib/util/os_util.rb +385 -0
- data/lib/util/permission_util.rb +31 -0
- data/lib/util/remote_dependency_util.rb +84 -0
- data/lib/util/ssh_util.rb +94 -0
- data/lib/view_processor.rb +129 -0
- data/lib/view_processor/augmented_simple_list.rb +44 -0
- data/lib/view_processor/hash_pretty_print.rb +123 -0
- data/lib/view_processor/simple_list.rb +156 -0
- data/lib/view_processor/table_print.rb +309 -0
- data/lib/violation.rb +86 -0
- data/lib/violation/attribute.rb +76 -0
- data/lib/violation/fix.rb +26 -0
- data/lib/violation/fix/result.rb +73 -0
- data/lib/violation/fix/result/error.rb +34 -0
- data/lib/violation/fix/set_attribute.rb +41 -0
- data/lib/violation/sub_classes.rb +60 -0
- data/puppet/manifests/init.pp +72 -0
- data/puppet/manifests/params.pp +16 -0
- data/puppet/r8meta.puppet.yml +35 -0
- data/puppet/templates/bash_profile.erb +2 -0
- data/puppet/templates/client.conf.erb +1 -0
- data/puppet/templates/dtkclient.erb +2 -0
- data/spec/component_module_spec.rb +34 -0
- data/spec/dependency_spec.rb +6 -0
- data/spec/dtk_shell_spec.rb +13 -0
- data/spec/dtk_spec.rb +33 -0
- data/spec/lib/spec_helper.rb +10 -0
- data/spec/lib/spec_thor.rb +108 -0
- data/spec/node_template_spec.rb +24 -0
- data/spec/project_spec.rb +6 -0
- data/spec/repo_spec.rb +7 -0
- data/spec/response_spec.rb +52 -0
- data/spec/service_module_spec.rb +38 -0
- data/spec/service_spec.rb +50 -0
- data/spec/state_change_spec.rb +7 -0
- data/spec/table_print_spec.rb +48 -0
- data/spec/target_spec.rb +57 -0
- data/spec/task_spec.rb +28 -0
- data/views/assembly/augmented_simple_list.rb +12 -0
- data/views/assembly_template/augmented_simple_list.rb +12 -0
- data/views/list_task/augmented_simple_list.rb +12 -0
- metadata +421 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
development_mode=false
|
|
2
|
+
meta_table_ttl=7200000 # time to live (ms)
|
|
3
|
+
meta_constants_ttl=7200000 # time to live (ms)
|
|
4
|
+
meta_pretty_print_ttl=7200000 # time to live (ms)
|
|
5
|
+
task_check_frequency=60 # check frequency for task status threads (seconds)
|
|
6
|
+
tail_log_frequency=2 # assembly - frequency between requests (seconds)
|
|
7
|
+
debug_task_frequency=5 # assembly - frequency between requests (seconds)
|
|
8
|
+
auto_commit_changes=false # autocommit for modules
|
|
9
|
+
verbose_rest_calls=false # logging of REST calls
|
|
10
|
+
|
|
11
|
+
# if relative path is used we will use HOME + relative path, apsoluth path will override this
|
|
12
|
+
module_location=component_modules
|
|
13
|
+
service_location=service_modules
|
|
14
|
+
test_module_location=test_modules
|
|
15
|
+
backups_location=backups
|
|
16
|
+
|
|
17
|
+
# server connection details
|
|
18
|
+
server_port=80
|
|
19
|
+
secure_connection_server_port=443
|
|
20
|
+
secure_connection=true
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (C) 2010-2016 dtk contributors
|
|
3
|
+
#
|
|
4
|
+
# This file is part of the dtk project.
|
|
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
|
+
#
|
|
19
|
+
# Singleton patern to hold configuration for dtk client.
|
|
20
|
+
#
|
|
21
|
+
# DEFAULT: Configuration
|
|
22
|
+
# DEVELOPMENT: Can add lib/config/local.conf, this is git ignored
|
|
23
|
+
#
|
|
24
|
+
# NOTE: Singleton here is not necessery since it will not persist in memory due
|
|
25
|
+
# to nature of DTK Client, but it is right approach for possible re-use
|
|
26
|
+
#
|
|
27
|
+
# Pririoty of load
|
|
28
|
+
# 1) LOCAL
|
|
29
|
+
# 2) EXTERNAL
|
|
30
|
+
# 3) DEFAULT
|
|
31
|
+
#
|
|
32
|
+
# NOTE: Default will be used if there some parameters missing in other configuration
|
|
33
|
+
#
|
|
34
|
+
require 'singleton'
|
|
35
|
+
|
|
36
|
+
dtk_require_from_base('util/os_util')
|
|
37
|
+
|
|
38
|
+
module DTK
|
|
39
|
+
class Configuration
|
|
40
|
+
include Singleton
|
|
41
|
+
|
|
42
|
+
EXTERNAL_APP_CONF = "client.conf"
|
|
43
|
+
DEVELOPMENT_CONF = 'local.conf'
|
|
44
|
+
DEFAULT_CONF = 'default.conf'
|
|
45
|
+
|
|
46
|
+
def self.get(name, default=nil)
|
|
47
|
+
Configuration.instance.get(name, default)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.[](k)
|
|
51
|
+
Configuration.instance.get(k)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def initialize
|
|
55
|
+
# default configuration
|
|
56
|
+
@cache = load_configuration_to_hash(File.expand_path("../#{DEFAULT_CONF}",__FILE__))
|
|
57
|
+
|
|
58
|
+
# we will not use local.conf from gemfile because client.conf is required so this is deprecated
|
|
59
|
+
if File.exist?(File.expand_path("../#{DEVELOPMENT_CONF}",__FILE__))
|
|
60
|
+
local_configuration = load_configuration_to_hash(File.expand_path("../#{DEVELOPMENT_CONF}",__FILE__))
|
|
61
|
+
# we override only values from local configuration
|
|
62
|
+
# that way developer does not have updates its local configuration all the time
|
|
63
|
+
@cache.merge!(local_configuration)
|
|
64
|
+
# if we have loaded local configuration we will not check external
|
|
65
|
+
return
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# We load this if there is no local configuration
|
|
69
|
+
external_file_location = File.join(::DTK::Client::OsUtil.dtk_local_folder(), "#{EXTERNAL_APP_CONF}")
|
|
70
|
+
|
|
71
|
+
if File.exist?(external_file_location)
|
|
72
|
+
external_configuration = load_configuration_to_hash(external_file_location)
|
|
73
|
+
@cache.merge!(external_configuration)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def get(name, default=nil)
|
|
78
|
+
return @cache[name.to_s] || default
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def load_configuration_to_hash(path_to_file)
|
|
84
|
+
configuration = Hash[*File.read(path_to_file).gsub(/#.+/,'').strip().gsub(/( |\t)+$/,'').split(/[=\n\r\r\n]+/)]
|
|
85
|
+
|
|
86
|
+
# check for types
|
|
87
|
+
return configuration.each do |k,v|
|
|
88
|
+
case v
|
|
89
|
+
when /^(true|false)$/
|
|
90
|
+
configuration[k] = v.eql?('true') ? true : false
|
|
91
|
+
when /^[0-9]+$/
|
|
92
|
+
configuration[k] = v.to_i
|
|
93
|
+
when /^[0-9\.]+$/
|
|
94
|
+
configuration[k] = v.to_f
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
development_mode=false
|
|
2
|
+
debug_grit=false
|
|
3
|
+
meta_table_ttl=7200000 # time to live (ms)
|
|
4
|
+
meta_constants_ttl=7200000 # time to live (ms)
|
|
5
|
+
meta_pretty_print_ttl=7200000 # time to live (ms)
|
|
6
|
+
task_check_frequency=60 # check frequency for task status threads (seconds)
|
|
7
|
+
tail_log_frequency=2 # assembly - frequency between requests (seconds)
|
|
8
|
+
debug_task_frequency=5 # assembly - frequency between requests (seconds)
|
|
9
|
+
auto_commit_changes=false # autocommit for modules
|
|
10
|
+
verbose_rest_calls=false # logging of REST calls
|
|
11
|
+
|
|
12
|
+
# if relative path is used we will use HOME + relative path, apsoluth path will override this
|
|
13
|
+
module_location=component_modules
|
|
14
|
+
service_location=service_modules
|
|
15
|
+
test_module_location=test_modules
|
|
16
|
+
backups_location=backups
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (C) 2010-2016 dtk contributors
|
|
3
|
+
#
|
|
4
|
+
# This file is part of the dtk project.
|
|
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
|
+
require 'net/http'
|
|
19
|
+
#require 'md5' => Ruby 1.8.7 specific
|
|
20
|
+
require File.expand_path('../util/os_util', File.dirname(__FILE__))
|
|
21
|
+
dtk_require("../commands")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
#
|
|
25
|
+
# Class dedicated for caching data on local system as well as for cookie management
|
|
26
|
+
#
|
|
27
|
+
class DiskCacher
|
|
28
|
+
include DTK::Client::CommandBase
|
|
29
|
+
extend DTK::Client::CommandBase
|
|
30
|
+
|
|
31
|
+
# file name to hold cookies
|
|
32
|
+
COOKIE_HOLDER_NAME = 'tempdtkstore'
|
|
33
|
+
FILE_DELIMITER = '--'
|
|
34
|
+
|
|
35
|
+
def initialize(cache_dir = DTK::Client::OsUtil.get_temp_location)
|
|
36
|
+
@cache_dir = cache_dir
|
|
37
|
+
@current_user = ::DTK::Client::Configurator.client_username
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def fetch(file_name, max_age = 0, use_mock_up = true)
|
|
41
|
+
file = Digest::MD5.hexdigest(file_name)
|
|
42
|
+
# current user is important so that there are no clashes in writting to temp file
|
|
43
|
+
# between multiple users on same machine
|
|
44
|
+
file_path = File.join(@cache_dir, "#{@current_user}#{FILE_DELIMITER}#{file}")
|
|
45
|
+
|
|
46
|
+
# we check if the file -- a MD5 hexdigest of the URL -- exists
|
|
47
|
+
# in the dir. If it does and the data is fresh, we just read
|
|
48
|
+
# data from the file and return
|
|
49
|
+
if File.exists? file_path
|
|
50
|
+
return File.new(file_path).read if ((Time.now - File.mtime(file_path)) < max_age)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# if the file does not exist (or if the data is not fresh), we
|
|
54
|
+
# make an get request and save it to a file
|
|
55
|
+
response_string = ""
|
|
56
|
+
response = get rest_url("metadata/get_metadata/#{file_name}")
|
|
57
|
+
|
|
58
|
+
if (response["status"] == "ok")
|
|
59
|
+
file = File.open(file_path, "w") do |data|
|
|
60
|
+
data << response_string = response["data"]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
return response_string
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def save_cookie(cookie_content)
|
|
68
|
+
file_path = File.join(@cache_dir, COOKIE_HOLDER_NAME)
|
|
69
|
+
File.open(file_path, "w") do |file|
|
|
70
|
+
Marshal.dump(cookie_content, file)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def load_cookie
|
|
75
|
+
file_path = File.join(@cache_dir, COOKIE_HOLDER_NAME)
|
|
76
|
+
cookie_content = File.exists?(file_path) ? File.open(file_path) {|f| Marshal.load(f)} : nil
|
|
77
|
+
cookie_content
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
data/lib/configurator.rb
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (C) 2010-2016 dtk contributors
|
|
3
|
+
#
|
|
4
|
+
# This file is part of the dtk project.
|
|
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
|
+
require 'rubygems'
|
|
19
|
+
require 'fileutils'
|
|
20
|
+
dtk_require_from_base('util/os_util')
|
|
21
|
+
|
|
22
|
+
module DTK
|
|
23
|
+
module Client
|
|
24
|
+
class Configurator
|
|
25
|
+
|
|
26
|
+
CONFIG_FILE = File.join(OsUtil.dtk_local_folder, "client.conf")
|
|
27
|
+
CRED_FILE = File.join(OsUtil.dtk_local_folder, ".connection")
|
|
28
|
+
DIRECT_ACCESS = File.join(OsUtil.dtk_local_folder, ".add_direct_access")
|
|
29
|
+
NODE_SSH_CREDENTIALS = File.join(OsUtil.dtk_local_folder, "ssh_credentials.yaml")
|
|
30
|
+
|
|
31
|
+
FileUtils.mkdir(OsUtil.dtk_local_folder) unless File.directory?(OsUtil.dtk_local_folder)
|
|
32
|
+
|
|
33
|
+
def self.check_config_exists
|
|
34
|
+
exists = true
|
|
35
|
+
if !File.exists?(CONFIG_FILE)
|
|
36
|
+
puts "", "Please enter the DTK server address (example: instance.dtk.io)"
|
|
37
|
+
header = File.read(File.expand_path('../lib/config/client.conf.header', File.dirname(__FILE__)))
|
|
38
|
+
generate_conf_file(CONFIG_FILE, [['server_host', 'Server address']], header)
|
|
39
|
+
exists = false
|
|
40
|
+
end
|
|
41
|
+
if !File.exists?(CRED_FILE)
|
|
42
|
+
puts "", "Please enter your DTK login details"
|
|
43
|
+
generate_conf_file(CRED_FILE, [['username', 'Username'], ['password', 'Password']], '')
|
|
44
|
+
exists = false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
exists
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.check_git
|
|
51
|
+
if OsUtil.which('git') == nil
|
|
52
|
+
OsUtil.put_warning "[WARNING]", "Can't find the 'git' command in you path. Please make sure git is installed in order to use all features of DTK Client.", :yellow
|
|
53
|
+
else
|
|
54
|
+
OsUtil.put_warning "[WARNING]", 'Git username not set. This can cause issues while using DTK Client. To set it, run `git config --global user.name "User Name"`', :yellow if `git config --get user.name` == ""
|
|
55
|
+
OsUtil.put_warning "[WARNING]", 'Git email not set. This can cause issues while using DTK Client. To set it, run `git config --global user.email "me@here.com"`', :yellow if `git config --get user.email` == ""
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# return true/false, .add_direct_access file location and ssk key file location
|
|
60
|
+
def self.check_direct_access
|
|
61
|
+
username_exists = check_for_username_entry(client_username())
|
|
62
|
+
ssh_key_path = SSHUtil.default_rsa_pub_key_path()
|
|
63
|
+
|
|
64
|
+
{:username_exists => username_exists, :file_path => DIRECT_ACCESS, :ssh_key_path => ssh_key_path}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.generate_conf_file(file_path, properties, header)
|
|
68
|
+
require 'highline/import'
|
|
69
|
+
property_template = []
|
|
70
|
+
|
|
71
|
+
properties.each do |p,d|
|
|
72
|
+
begin
|
|
73
|
+
trap("INT") {
|
|
74
|
+
puts "", "Exiting..."
|
|
75
|
+
abort
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
value = ask("#{d}: ") { |q| q.echo = false if p == 'password'}
|
|
79
|
+
property_template << [p,value]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
File.open(file_path, 'w') do |f|
|
|
83
|
+
f.puts(header)
|
|
84
|
+
property_template.each do |prop|
|
|
85
|
+
f.puts("#{prop[0]}=#{prop[1]}")
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def self.regenerate_conf_file(file_path, properties, header)
|
|
91
|
+
File.open(file_path, 'w') do |f|
|
|
92
|
+
f.puts(header)
|
|
93
|
+
properties.each do |prop|
|
|
94
|
+
f.puts("#{prop[0]}=#{prop[1]}")
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def self.create_missing_clone_dirs
|
|
100
|
+
FileUtils.mkdir(OsUtil.component_clone_location) unless File.directory?(OsUtil.component_clone_location)
|
|
101
|
+
FileUtils.mkdir(OsUtil.service_clone_location) unless File.directory?(OsUtil.service_clone_location)
|
|
102
|
+
FileUtils.mkdir(OsUtil.test_clone_location) unless File.directory?(OsUtil.test_clone_location)
|
|
103
|
+
FileUtils.mkdir(OsUtil.backups_location) unless File.directory?(OsUtil.backups_location)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def self.parse_key_value_file(file)
|
|
108
|
+
# adapted from mcollective config
|
|
109
|
+
ret = Hash.new
|
|
110
|
+
raise DTK::Client::DtkError,"Config file (#{file}) does not exists" unless File.exists?(file)
|
|
111
|
+
File.open(file).each do |line|
|
|
112
|
+
# strip blank spaces, tabs etc off the end of all lines
|
|
113
|
+
line.gsub!(/\s*$/, "")
|
|
114
|
+
unless line =~ /^#|^$/
|
|
115
|
+
if (line =~ /(.+?)\s*=\s*(.+)/)
|
|
116
|
+
key = $1
|
|
117
|
+
val = $2
|
|
118
|
+
ret[key.to_sym] = val
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
ret
|
|
123
|
+
end
|
|
124
|
+
def self.add_current_user_to_direct_access()
|
|
125
|
+
username = client_username()
|
|
126
|
+
|
|
127
|
+
File.open(DIRECT_ACCESS, 'a') do |file|
|
|
128
|
+
file.puts(username)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
true
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def self.client_username()
|
|
135
|
+
parse_key_value_file(CRED_FILE)[:username]
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
#
|
|
139
|
+
# Method will check if there is username entry in DIRECT_ACCESS file
|
|
140
|
+
#
|
|
141
|
+
def self.check_for_username_entry(username)
|
|
142
|
+
if File.exists?(DIRECT_ACCESS)
|
|
143
|
+
File.open(DIRECT_ACCESS).each do |line|
|
|
144
|
+
if line.strip.eql?(username)
|
|
145
|
+
return true
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
return false
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def self.ask_catalog_credentials()
|
|
154
|
+
are_there_creds = Console.confirmation_prompt("Do you have DTK catalog credentials", true)
|
|
155
|
+
property_template = {}
|
|
156
|
+
if are_there_creds
|
|
157
|
+
property_template = self.enter_catalog_credentials()
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
property_template
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def self.enter_catalog_credentials()
|
|
164
|
+
property_template = {}
|
|
165
|
+
# needed to preserve the order for ruby 1.8.7
|
|
166
|
+
# ruby 1.8 does not preserve order of insertation
|
|
167
|
+
wizard_values = { :username => 'Catalog Username', :password => 'Catalog Password' }
|
|
168
|
+
[:username, :password].each do |p|
|
|
169
|
+
value = ask("#{wizard_values[p]}: ") { |q| q.echo = false if p == :password }
|
|
170
|
+
property_template.store(p, value)
|
|
171
|
+
end
|
|
172
|
+
property_template
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (C) 2010-2016 dtk contributors
|
|
3
|
+
#
|
|
4
|
+
# This file is part of the dtk project.
|
|
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
|
+
module DTK
|
|
19
|
+
module Client
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
# This class is used to reroute commands/tasks (Method invocations) from one context (Class) to another
|
|
23
|
+
#
|
|
24
|
+
class ContextRouter
|
|
25
|
+
|
|
26
|
+
extend DTK::Client::Auxiliary
|
|
27
|
+
|
|
28
|
+
# This method invokes target context task
|
|
29
|
+
def self.routeTask(target_context, target_method, target_context_params, conn)
|
|
30
|
+
target_context = target_context.to_s
|
|
31
|
+
target_method = target_method.to_s
|
|
32
|
+
|
|
33
|
+
# Initing required params and invoking target_context.target_method
|
|
34
|
+
load_command(target_context)
|
|
35
|
+
target_context_class = DTK::Client.const_get "#{cap_form(target_context)}"
|
|
36
|
+
|
|
37
|
+
ret = target_context_class.execute_from_cli(conn, target_method, target_context_params, [], false)
|
|
38
|
+
ret.kind_of?(Response::NoOp) ? Response::Ok.new() : ret
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/core.rb
ADDED
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (C) 2010-2016 dtk contributors
|
|
3
|
+
#
|
|
4
|
+
# This file is part of the dtk project.
|
|
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
|
+
#TODO: user common utils in DTK::Common::Rest
|
|
19
|
+
|
|
20
|
+
require 'rubygems'
|
|
21
|
+
require 'singleton'
|
|
22
|
+
require 'restclient'
|
|
23
|
+
require 'colorize'
|
|
24
|
+
require 'json'
|
|
25
|
+
require 'pp'
|
|
26
|
+
|
|
27
|
+
# Development Gems
|
|
28
|
+
if ::DTK::Configuration.get(:development_mode)
|
|
29
|
+
require 'ap'
|
|
30
|
+
# require 'looksee'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
#TODO: for testing; fix by pass in commadn line argument
|
|
34
|
+
#RestClient.log = STDOUT
|
|
35
|
+
|
|
36
|
+
dtk_require_from_base('domain/response')
|
|
37
|
+
dtk_require_from_base('util/os_util')
|
|
38
|
+
dtk_require_from_base('util/ssh_util')
|
|
39
|
+
dtk_require_from_base('util/common_util')
|
|
40
|
+
dtk_require_from_base('util/permission_util')
|
|
41
|
+
dtk_require_from_base('util/remote_dependency_util')
|
|
42
|
+
dtk_require_from_base('util/module_util')
|
|
43
|
+
dtk_require_from_base('shell/message_queue')
|
|
44
|
+
|
|
45
|
+
dtk_require("config/configuration")
|
|
46
|
+
|
|
47
|
+
def top_level_execute(entity_name, method_name, context_params=nil, options_args=nil, shell_execute=false)
|
|
48
|
+
begin
|
|
49
|
+
top_level_execute_core(entity_name, method_name, context_params, options_args, shell_execute)
|
|
50
|
+
rescue DTK::Client::DtkLoginRequiredError
|
|
51
|
+
# re-logging user and repeating request
|
|
52
|
+
DTK::Client::OsUtil.print("Session expired: re-establishing session & repeating given task", :yellow)
|
|
53
|
+
DTK::Client::Session.re_initialize
|
|
54
|
+
top_level_execute_core(entity_name, method_name, context_params, options_args, shell_execute)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def top_level_execute_core(entity_name, method_name, context_params=nil, options_args=nil, shell_execute=false)
|
|
59
|
+
extend DTK::Client::OsUtil
|
|
60
|
+
|
|
61
|
+
entity_class = nil
|
|
62
|
+
|
|
63
|
+
begin
|
|
64
|
+
include DTK::Client::Auxiliary
|
|
65
|
+
|
|
66
|
+
entity_name = entity_name.gsub("-","_")
|
|
67
|
+
load_command(entity_name)
|
|
68
|
+
conn = DTK::Client::Session.get_connection
|
|
69
|
+
|
|
70
|
+
# if connection parameters are not set up properly then don't execute any command
|
|
71
|
+
return if validate_connection(conn)
|
|
72
|
+
|
|
73
|
+
# call proper thor class and task
|
|
74
|
+
entity_class = DTK::Client.const_get "#{cap_form(entity_name)}"
|
|
75
|
+
|
|
76
|
+
# call forwarding, in case there is no task for given entity we switch to last (n-context) and try than
|
|
77
|
+
unless (entity_class.task_names.include?(method_name))
|
|
78
|
+
entity_class = DTK::Client.const_get "#{cap_form(context_params.last_entity_name.to_s)}"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
response_ruby_obj = entity_class.execute_from_cli(conn,method_name,context_params,options_args,shell_execute)
|
|
82
|
+
|
|
83
|
+
# it will raise DTK::Client::Error in case of error response
|
|
84
|
+
print_method_response!(response_ruby_obj)
|
|
85
|
+
|
|
86
|
+
# process/print queued message from server
|
|
87
|
+
DTK::Shell::MessageQueue.print_messages
|
|
88
|
+
|
|
89
|
+
rescue DTK::Client::DtkLoginRequiredError => e
|
|
90
|
+
# this error is handled in method above
|
|
91
|
+
raise e
|
|
92
|
+
rescue DTK::Client::DSLParsing => e
|
|
93
|
+
DTK::Client::OsUtil.print(e.message, :red)
|
|
94
|
+
rescue DTK::Client::DtkValidationError => e
|
|
95
|
+
validation_message = e.message
|
|
96
|
+
|
|
97
|
+
# if !e.skip_usage_info && entity_class && method_name
|
|
98
|
+
# usage_info = entity_class.get_usage_info(entity_name, method_name)
|
|
99
|
+
# validation_message += ", usage: #{usage_info}"
|
|
100
|
+
# end
|
|
101
|
+
|
|
102
|
+
if e.display_usage_info && entity_class && method_name
|
|
103
|
+
usage_info = entity_class.get_usage_info(entity_name, method_name)
|
|
104
|
+
validation_message += ", usage: #{usage_info}"
|
|
105
|
+
|
|
106
|
+
validation_message.gsub!("^^", '') if validation_message.include?("^^")
|
|
107
|
+
validation_message.gsub!("HIDE_FROM_BASE ", '') if validation_message.include?("HIDE_FROM_BASE")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
DTK::Client::OsUtil.print(validation_message, :yellow)
|
|
111
|
+
rescue DTK::Client::DtkError => e
|
|
112
|
+
# this are expected application errors
|
|
113
|
+
DtkLogger.instance.error_pp(e.message, e.backtrace)
|
|
114
|
+
rescue Exception => e
|
|
115
|
+
client_internal_error = DTK::Client::DtkError::Client.label()
|
|
116
|
+
DtkLogger.instance.fatal_pp("[#{client_internal_error}] DTK has encountered an error #{e.class}: #{e.message}", e.backtrace)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def print_method_response!(response_ruby_obj)
|
|
121
|
+
# this will raise error if found
|
|
122
|
+
DTK::Client::ResponseErrorHandler.check(response_ruby_obj)
|
|
123
|
+
|
|
124
|
+
# this will find appropriate render adapter and give output, returns boolean
|
|
125
|
+
if print = response_ruby_obj.render_data
|
|
126
|
+
print = [print] unless print.kind_of?(Array)
|
|
127
|
+
print.each do |el|
|
|
128
|
+
if el.kind_of?(String)
|
|
129
|
+
el.each_line{|l| STDOUT << l}
|
|
130
|
+
else
|
|
131
|
+
PP.pp(el,STDOUT)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def load_command(command_name)
|
|
138
|
+
parser_adapter = DTK::Client::Config[:cli_parser] || "thor"
|
|
139
|
+
|
|
140
|
+
dtk_nested_require("parser/adapters",parser_adapter)
|
|
141
|
+
dtk_nested_require("commands/#{parser_adapter}",command_name)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# check if connection is set up properly
|
|
145
|
+
def validate_connection(connection)
|
|
146
|
+
if connection.connection_error?
|
|
147
|
+
connection.print_warning
|
|
148
|
+
puts "\nDTK will now exit. Please set up your connection properly and try again."
|
|
149
|
+
return true
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
false
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# check if .add_direct_access file exists, if not then add direct access and create .add_direct_access file
|
|
156
|
+
def resolve_direct_access(params, config_exists=nil)
|
|
157
|
+
return if params[:username_exists]
|
|
158
|
+
|
|
159
|
+
puts "Processing ..." if config_exists
|
|
160
|
+
# check to see if catalog credentials are set
|
|
161
|
+
conn = DTK::Client::Session.get_connection
|
|
162
|
+
response = conn.post DTK::Client::CommandBase.class, conn.rest_url("account/check_catalog_credentials"), {}
|
|
163
|
+
|
|
164
|
+
# set catalog credentails
|
|
165
|
+
if response.ok? && !response.data['catalog_credentials_set']
|
|
166
|
+
# setting up catalog credentials
|
|
167
|
+
catalog_creds = DTK::Client::Configurator.ask_catalog_credentials
|
|
168
|
+
unless catalog_creds.empty?
|
|
169
|
+
response = conn.post DTK::Client::CommandBase.class, conn.rest_url("account/set_catalog_credentials"), { :username => catalog_creds[:username], :password => catalog_creds[:password], :validate => true}
|
|
170
|
+
if errors = response['errors']
|
|
171
|
+
DTK::Client::OsUtil.print("#{errors.first['message']} You will have to set catalog credentials manually ('dtk account set-catalog-credentials').", :yellow)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# response = DTK::Client::Account.add_access(params[:ssh_key_path])
|
|
177
|
+
response, matched_pub_key, matched_username = DTK::Client::Account.add_key(params[:ssh_key_path], true, "#{DTK::Client::Session.connection_username}-client")
|
|
178
|
+
|
|
179
|
+
if !response.ok?
|
|
180
|
+
DTK::Client::OsUtil.print("We were not able to add access for current user. #{response.error_message}. In order to properly use dtk-shell you will have to add access manually ('dtk account add-ssh-key').\n", :yellow)
|
|
181
|
+
elsif matched_pub_key
|
|
182
|
+
# message will be displayed by add key # TODO: Refactor this flow
|
|
183
|
+
DTK::Client::OsUtil.print("Provided SSH PUB key has already been added.", :yellow)
|
|
184
|
+
DTK::Client::Configurator.add_current_user_to_direct_access
|
|
185
|
+
elsif matched_username
|
|
186
|
+
DTK::Client::OsUtil.print("User with provided name already exists.", :yellow)
|
|
187
|
+
else
|
|
188
|
+
# commented out because 'add_key' method called above will also print the same message
|
|
189
|
+
# DTK::Client::OsUtil.print("Your SSH PUB key has been successfully added.", :yellow)
|
|
190
|
+
DTK::Client::Configurator.add_current_user_to_direct_access
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
response
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
module DTK
|
|
197
|
+
module Client
|
|
198
|
+
class ResponseErrorHandler
|
|
199
|
+
class << self
|
|
200
|
+
|
|
201
|
+
def check_for_session_expiried(response)
|
|
202
|
+
error_code = nil
|
|
203
|
+
if response && response['errors']
|
|
204
|
+
response['errors'].each do |err|
|
|
205
|
+
error_code = err["code"]||(err["errors"] && err["errors"].first["code"])
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
return (error_code == "forbidden")
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def check(response)
|
|
213
|
+
DtkError.raise_if_error?(response)
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
class Log
|
|
219
|
+
#TODO Stubs
|
|
220
|
+
def self.info(msg)
|
|
221
|
+
pp "info: #{msg}"
|
|
222
|
+
end
|
|
223
|
+
def self.error(msg)
|
|
224
|
+
pp "error: #{msg}"
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
module ParseFile
|
|
229
|
+
|
|
230
|
+
def parse_key_value_file(file)
|
|
231
|
+
DTK::Client::Configurator.parse_key_value_file(file)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
end
|
|
235
|
+
class Config < Hash
|
|
236
|
+
include Singleton
|
|
237
|
+
include ParseFile
|
|
238
|
+
dtk_require_from_base('configurator')
|
|
239
|
+
|
|
240
|
+
CONFIG_FILE = ::DTK::Client::Configurator::CONFIG_FILE
|
|
241
|
+
CRED_FILE = ::DTK::Client::Configurator::CRED_FILE
|
|
242
|
+
|
|
243
|
+
REQUIRED_KEYS = [:server_host]
|
|
244
|
+
|
|
245
|
+
def self.[](k)
|
|
246
|
+
Config.instance[k]
|
|
247
|
+
end
|
|
248
|
+
private
|
|
249
|
+
def initialize
|
|
250
|
+
set_defaults
|
|
251
|
+
load_config_file
|
|
252
|
+
validate
|
|
253
|
+
end
|
|
254
|
+
def set_defaults
|
|
255
|
+
self[:server_port] = 80
|
|
256
|
+
self[:assembly_module_base_location] = 'assemblies'
|
|
257
|
+
self[:secure_connection] = true
|
|
258
|
+
self[:secure_connection_server_port] = 443
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def load_config_file
|
|
262
|
+
parse_key_value_file(CONFIG_FILE).each{|k,v|self[k]=v}
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def validate
|
|
266
|
+
#TODO: need to check for legal values
|
|
267
|
+
missing_keys = REQUIRED_KEYS - keys
|
|
268
|
+
raise DTK::Client::DtkError, "Missing config keys (#{missing_keys.join(",")}). Please check your configuration file #{CONFIG_FILE} for required keys!" unless missing_keys.empty?
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
##
|
|
275
|
+
# Session Singleton we will use to hold connection instance, just a singleton wrapper.
|
|
276
|
+
# During shell input it will be needed only once, so singleton was obvious solution.
|
|
277
|
+
#
|
|
278
|
+
class Session
|
|
279
|
+
include Singleton
|
|
280
|
+
|
|
281
|
+
attr_accessor :conn
|
|
282
|
+
|
|
283
|
+
def initialize
|
|
284
|
+
@conn = DTK::Client::Conn.new
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def self.get_connection
|
|
288
|
+
Session.instance.conn
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def self.connection_username
|
|
292
|
+
Session.instance.conn.get_username
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def self.re_initialize
|
|
296
|
+
Session.instance.conn = nil
|
|
297
|
+
Session.instance.conn = DTK::Client::Conn.new
|
|
298
|
+
Session.instance.conn.cookies
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def self.logout
|
|
302
|
+
# from this point @conn is not valid, since there are no cookies set
|
|
303
|
+
Session.instance.conn.logout
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# opts can have key
|
|
307
|
+
# :command_class
|
|
308
|
+
def self.post(route, body, opts = {})
|
|
309
|
+
command_class = opts[:command_class] || Class
|
|
310
|
+
conn = Session.instance.conn
|
|
311
|
+
conn.post(command_class, conn.rest_url(route), body)
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
class Conn
|
|
316
|
+
def initialize
|
|
317
|
+
@cookies = Hash.new
|
|
318
|
+
@connection_error = nil
|
|
319
|
+
login
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
VERBOSE_MODE_ON = ::DTK::Configuration.get(:verbose_rest_calls)
|
|
323
|
+
|
|
324
|
+
attr_reader :connection_error, :cookies
|
|
325
|
+
|
|
326
|
+
if VERBOSE_MODE_ON
|
|
327
|
+
require 'ap'
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def self.get_timeout
|
|
331
|
+
DefaultRestOpts[:timeout]
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def self.set_timeout(timeout_sec)
|
|
335
|
+
DefaultRestOpts[:timeout] = timeout_sec
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def get_username
|
|
339
|
+
get_credentials[:username]
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def rest_url(route=nil)
|
|
343
|
+
protocol, port = "http", Config[:server_port].to_s
|
|
344
|
+
protocol, port = "https", Config[:secure_connection_server_port].to_s if Config[:secure_connection] == "true"
|
|
345
|
+
|
|
346
|
+
"#{protocol}://#{Config[:server_host]}:#{port}/rest/#{route}"
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def get(command_class,url)
|
|
350
|
+
ap "GET #{url}" if VERBOSE_MODE_ON
|
|
351
|
+
|
|
352
|
+
check_and_wrap_response(command_class, Proc.new { json_parse_if_needed(get_raw(url)) })
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def post(command_class,url,body=nil)
|
|
356
|
+
if VERBOSE_MODE_ON
|
|
357
|
+
ap "POST (REST) #{url}"
|
|
358
|
+
ap "params: "
|
|
359
|
+
ap body
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
check_and_wrap_response(command_class, Proc.new { json_parse_if_needed(post_raw(url,body)) })
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
def post_file(command_class,url,body=nil)
|
|
366
|
+
if VERBOSE_MODE_ON
|
|
367
|
+
ap "POST (FILE) #{url}"
|
|
368
|
+
ap "params: "
|
|
369
|
+
ap body
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
check_and_wrap_response(command_class, Proc.new { json_parse_if_needed(post_raw(url,body,{:content_type => 'avro/binary'})) })
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
# method will repeat request in case session has expired
|
|
376
|
+
def check_and_wrap_response(command_class, rest_method_func)
|
|
377
|
+
response = rest_method_func.call
|
|
378
|
+
|
|
379
|
+
if ResponseErrorHandler.check_for_session_expiried(response)
|
|
380
|
+
# re-logging user and repeating request
|
|
381
|
+
DTK::Client::OsUtil.print("Session expired: re-establishing session & re-trying request ...", :yellow)
|
|
382
|
+
@cookies = DTK::Client::Session.re_initialize
|
|
383
|
+
response = rest_method_func.call
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
response_obj = Response.new(command_class, response)
|
|
387
|
+
|
|
388
|
+
# queue messages from server to be displayed later
|
|
389
|
+
DTK::Shell::MessageQueue.process_response(response_obj)
|
|
390
|
+
|
|
391
|
+
response_obj
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def connection_error?
|
|
397
|
+
return !@connection_error.nil?
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
def logout
|
|
401
|
+
response = get_raw rest_url("user/process_logout")
|
|
402
|
+
|
|
403
|
+
# save cookies - no need to persist them
|
|
404
|
+
# DiskCacher.new.save_cookie(@cookies)
|
|
405
|
+
|
|
406
|
+
raise DTK::Client::DtkError, "Failed to logout, and terminate session!" unless response
|
|
407
|
+
@cookies = nil
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
##
|
|
411
|
+
# Method will warn user that connection could not be established. User should check configuration
|
|
412
|
+
# to make sure that connection is properly set.
|
|
413
|
+
#
|
|
414
|
+
def print_warning
|
|
415
|
+
creds = get_credentials
|
|
416
|
+
puts "[WARNING] Unable to connect to server, please check you configuration."
|
|
417
|
+
puts "========================== Configuration =========================="
|
|
418
|
+
printf "%15s %s\n", "REST endpoint:", rest_url
|
|
419
|
+
printf "%15s %s\n", "Username:", "#{creds[:username]}"
|
|
420
|
+
printf "%15s %s\n", "Password:", "#{creds[:password] ? creds[:password].gsub(/./,'*') : 'No password set'}"
|
|
421
|
+
puts "==================================================================="
|
|
422
|
+
|
|
423
|
+
if self.connection_error['errors'].first['errors']
|
|
424
|
+
error_code = self.connection_error['errors'].first['errors'].first['code']
|
|
425
|
+
print " Error code: "
|
|
426
|
+
DTK::Client::OsUtil.print(error_code, :red)
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
private
|
|
431
|
+
|
|
432
|
+
include ParseFile
|
|
433
|
+
|
|
434
|
+
def login
|
|
435
|
+
creds = get_credentials
|
|
436
|
+
response = post_raw rest_url("user/process_login"),creds
|
|
437
|
+
errors = response['errors']
|
|
438
|
+
|
|
439
|
+
if response.kind_of?(Common::Response) and not response.ok?
|
|
440
|
+
if (errors && errors.first['code']=="pg_error")
|
|
441
|
+
DTK::Client::OsUtil.print(errors.first['message'].gsub!("403 Forbidden", "[PG_ERROR]"), :red)
|
|
442
|
+
exit
|
|
443
|
+
end
|
|
444
|
+
@connection_error = response
|
|
445
|
+
else
|
|
446
|
+
@cookies = response.cookies
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
def set_credentials(username, password)
|
|
451
|
+
@parsed_credentials = { :username => username, :password => password}
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
def get_credentials
|
|
455
|
+
unless @parsed_credentials
|
|
456
|
+
cred_file = Config::CRED_FILE
|
|
457
|
+
raise DTK::Client::DtkError,"Authorization configuration file (#{cred_file}) does not exist" unless File.exists?(cred_file)
|
|
458
|
+
ret = parse_key_value_file(cred_file)
|
|
459
|
+
[:username,:password].each{ |k| raise DTK::Client::DtkError, "cannot find #{k}" unless ret[k] }
|
|
460
|
+
@parsed_credentials = ret
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
@parsed_credentials
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
####
|
|
467
|
+
RestClientWrapper = Common::Response::RestClientWrapper
|
|
468
|
+
|
|
469
|
+
# In development mode we want bigger timeout allowing us to debbug on server while still
|
|
470
|
+
# keeping connection alive and receivinga response
|
|
471
|
+
if ::DTK::Configuration.get(:development_mode)
|
|
472
|
+
DefaultRestOpts = {:timeout => 2000, :open_timeout => 10, :error_response_class => Client::Response::Error}
|
|
473
|
+
# DefaultRestOpts = {:timeout => 50, :open_timeout => 2, :error_response_class => Client::Response::Error}
|
|
474
|
+
else
|
|
475
|
+
DefaultRestOpts = {:timeout => 300, :open_timeout => 10, :error_response_class => Client::Response::Error}
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
# enable SSL verification
|
|
479
|
+
DefaultRestOpts.merge!(:verify_ssl => OpenSSL::SSL::VERIFY_PEER)
|
|
480
|
+
# Net:HTTP from Ruby 1.8.7 doesn't verify SSL certs correctly
|
|
481
|
+
# this is a CA bundle downloaded from http://curl.haxx.se/docs/caextract.html,
|
|
482
|
+
# and it will only be used for 1.8.7, otherwise the default (system) CA will be used
|
|
483
|
+
DefaultRestOpts.merge!(:ssl_ca_file => File.expand_path('../lib/config/cacert.pem', File.dirname(__FILE__)))
|
|
484
|
+
|
|
485
|
+
def get_raw(url)
|
|
486
|
+
RestClientWrapper.get_raw(url, {}, DefaultRestOpts.merge(:cookies => @cookies))
|
|
487
|
+
end
|
|
488
|
+
def post_raw(url,body,params={})
|
|
489
|
+
RestClientWrapper.post_raw(url, body, DefaultRestOpts.merge(:cookies => @cookies).merge(params))
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
def json_parse_if_needed(item)
|
|
493
|
+
RestClientWrapper.json_parse_if_needed(item)
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
end
|
|
497
|
+
end
|