dtk-client 0.5.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/Gemfile +5 -0
- data/Gemfile_dev +12 -0
- data/README.md +78 -0
- data/bin/dtk +54 -0
- data/bin/dtk-shell +15 -0
- data/dtk-client.gemspec +49 -0
- data/lib/auxiliary.rb +13 -0
- data/lib/bundler_monkey_patch.rb +9 -0
- data/lib/client.rb +48 -0
- data/lib/command_helper.rb +16 -0
- data/lib/command_helpers/git_repo.rb +391 -0
- data/lib/command_helpers/jenkins_client/config_xml.rb +271 -0
- data/lib/command_helpers/jenkins_client.rb +91 -0
- data/lib/command_helpers/service_importer.rb +99 -0
- data/lib/command_helpers/service_link.rb +18 -0
- data/lib/command_helpers/ssh_processing.rb +43 -0
- data/lib/commands/common/thor/assembly_workspace.rb +1089 -0
- data/lib/commands/common/thor/clone.rb +39 -0
- data/lib/commands/common/thor/common.rb +34 -0
- data/lib/commands/common/thor/edit.rb +168 -0
- data/lib/commands/common/thor/list_diffs.rb +84 -0
- data/lib/commands/common/thor/pull_clone_changes.rb +11 -0
- data/lib/commands/common/thor/pull_from_remote.rb +99 -0
- data/lib/commands/common/thor/purge_clone.rb +26 -0
- data/lib/commands/common/thor/push_clone_changes.rb +45 -0
- data/lib/commands/common/thor/push_to_remote.rb +45 -0
- data/lib/commands/common/thor/reparse.rb +36 -0
- data/lib/commands/common/thor/set_required_params.rb +29 -0
- data/lib/commands/common/thor/task_status.rb +81 -0
- data/lib/commands/thor/account.rb +213 -0
- data/lib/commands/thor/assembly.rb +329 -0
- data/lib/commands/thor/attribute.rb +62 -0
- data/lib/commands/thor/component.rb +52 -0
- data/lib/commands/thor/component_module.rb +829 -0
- data/lib/commands/thor/component_template.rb +153 -0
- data/lib/commands/thor/dependency.rb +18 -0
- data/lib/commands/thor/developer.rb +105 -0
- data/lib/commands/thor/dtk.rb +117 -0
- data/lib/commands/thor/library.rb +107 -0
- data/lib/commands/thor/node.rb +411 -0
- data/lib/commands/thor/node_group.rb +211 -0
- data/lib/commands/thor/node_template.rb +88 -0
- data/lib/commands/thor/project.rb +17 -0
- data/lib/commands/thor/provider.rb +155 -0
- data/lib/commands/thor/repo.rb +35 -0
- data/lib/commands/thor/service.rb +656 -0
- data/lib/commands/thor/service_module.rb +806 -0
- data/lib/commands/thor/state_change.rb +10 -0
- data/lib/commands/thor/target.rb +94 -0
- data/lib/commands/thor/task.rb +100 -0
- data/lib/commands/thor/utils.rb +4 -0
- data/lib/commands/thor/workspace.rb +437 -0
- data/lib/commands.rb +40 -0
- data/lib/config/cacert.pem +3785 -0
- data/lib/config/client.conf.header +18 -0
- data/lib/config/configuration.rb +82 -0
- data/lib/config/default.conf +14 -0
- data/lib/config/disk_cacher.rb +60 -0
- data/lib/configurator.rb +92 -0
- data/lib/context_router.rb +23 -0
- data/lib/core.rb +460 -0
- data/lib/domain/git_adapter.rb +221 -0
- data/lib/domain/response.rb +234 -0
- data/lib/dtk-client/version.rb +3 -0
- data/lib/dtk_constants.rb +23 -0
- data/lib/dtk_logger.rb +96 -0
- data/lib/error.rb +74 -0
- data/lib/git-logs/git.log +0 -0
- data/lib/parser/adapters/option_parser.rb +53 -0
- data/lib/parser/adapters/thor/common_option_defs.rb +12 -0
- data/lib/parser/adapters/thor.rb +509 -0
- data/lib/require_first.rb +87 -0
- data/lib/search_hash.rb +27 -0
- data/lib/shell/context.rb +975 -0
- data/lib/shell/context_aux.rb +29 -0
- data/lib/shell/domain.rb +447 -0
- data/lib/shell/header_shell.rb +27 -0
- data/lib/shell/help_monkey_patch.rb +221 -0
- data/lib/shell/interactive_wizard.rb +233 -0
- data/lib/shell/parse_monkey_patch.rb +22 -0
- data/lib/shell/status_monitor.rb +105 -0
- data/lib/shell.rb +219 -0
- data/lib/util/console.rb +143 -0
- data/lib/util/dtk_puppet.rb +46 -0
- data/lib/util/os_util.rb +265 -0
- data/lib/view_processor/augmented_simple_list.rb +27 -0
- data/lib/view_processor/hash_pretty_print.rb +106 -0
- data/lib/view_processor/simple_list.rb +139 -0
- data/lib/view_processor/table_print.rb +277 -0
- data/lib/view_processor.rb +112 -0
- data/puppet/manifests/init.pp +72 -0
- data/puppet/manifests/params.pp +16 -0
- data/puppet/r8meta.puppet.yml +18 -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/assembly_spec.rb +50 -0
- data/spec/assembly_template_spec.rb +51 -0
- data/spec/component_template_spec.rb +40 -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 +105 -0
- data/spec/module_spec.rb +35 -0
- data/spec/node_spec.rb +43 -0
- data/spec/node_template_spec.rb +25 -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_spec.rb +41 -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 +351 -0
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'jenkins-client'
|
2
|
+
module DTK; module Client
|
3
|
+
class JenkinsClient
|
4
|
+
require File.expand_path('jenkins_client/config_xml', File.dirname(__FILE__))
|
5
|
+
|
6
|
+
def self.create_service_module_project(module_id,module_name,repo_url,branch)
|
7
|
+
jenkins_project_name = module_name
|
8
|
+
config_xml_contents = ConfigXML.generate_service_module_project(repo_url,module_id,branch)
|
9
|
+
connection().create_job(jenkins_project_name,config_xml_contents)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.create_service_module_project?(module_id,module_name,repo_url,branch)
|
13
|
+
jenkins_project_name = module_name
|
14
|
+
jobs = get_jobs()||[]
|
15
|
+
#no op if job exists already
|
16
|
+
unless jobs.find{|j|j["name"] == jenkins_project_name}
|
17
|
+
create_service_module_project(module_id,module_name,repo_url,branch)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.create_assembly_project(assembly_name,assembly_id)
|
22
|
+
jenkins_project_name = assembly_name.gsub(/::/,"-")
|
23
|
+
config_xml_contents = ConfigXML.generate_assembly_project(assembly_id)
|
24
|
+
connection().create_job(jenkins_project_name,config_xml_contents)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.create_assembly_project?(assembly_name,assembly_id)
|
28
|
+
jenkins_project_name = assembly_name.gsub(/::/,"-")
|
29
|
+
jobs = get_jobs()||[]
|
30
|
+
#no op if job exists already
|
31
|
+
unless jobs.find{|j|j["name"] == jenkins_project_name}
|
32
|
+
create_assembly_project(assembly_name,assembly_id)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.get_jobs()
|
37
|
+
connection().get_jobs()
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def self.connection()
|
42
|
+
return @connection if @connection
|
43
|
+
#TODO: hardwired
|
44
|
+
connection_hash = {
|
45
|
+
:username => "rich",
|
46
|
+
:password => "test",
|
47
|
+
:url => "http://ec2-107-22-254-226.compute-1.amazonaws.com:8080"
|
48
|
+
}
|
49
|
+
@connection = Connection.new(connection_hash)
|
50
|
+
end
|
51
|
+
|
52
|
+
class Connection < Hash
|
53
|
+
def initialize(connection_hash)
|
54
|
+
super()
|
55
|
+
merge!(connection_hash)
|
56
|
+
set_connection()
|
57
|
+
end
|
58
|
+
def create_job(job_name,config_xml_contents)
|
59
|
+
::Jenkins::Client::Job.create(job_name, config_xml_contents)
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_info()
|
63
|
+
get('api/json')
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_jobs()
|
67
|
+
get_info()["jobs"]
|
68
|
+
end
|
69
|
+
private
|
70
|
+
#TODO: one issue with the jenkins-client adapter is that it a singleton and thus only allows connection under one user to one jenkins server
|
71
|
+
def set_connection()
|
72
|
+
::Jenkins::Client.configure do |c|
|
73
|
+
c.username = self[:username]
|
74
|
+
c.password = self[:password]
|
75
|
+
c.url = self[:url]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def get(path)
|
80
|
+
faraday_response = ::Jenkins::Client.get(path)
|
81
|
+
unless [200].include?(faraday_response.status)
|
82
|
+
raise Error.new("Bad response from Jenkins (status = #{faraday_response.status.to_s})")
|
83
|
+
end
|
84
|
+
faraday_response.body
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end; end
|
89
|
+
|
90
|
+
|
91
|
+
|
@@ -0,0 +1,99 @@
|
|
1
|
+
dtk_require_from_base('configurator')
|
2
|
+
module DTK::Client
|
3
|
+
#
|
4
|
+
# Main purpose of this module is to recognize which local modules are missing based on
|
5
|
+
# name, namespace, version and for those missing component module module will call
|
6
|
+
# module#clone and module#import_dtkn method to get missing component modules
|
7
|
+
#
|
8
|
+
module ServiceImporter
|
9
|
+
def create_missing_clone_dirs()
|
10
|
+
::DTK::Client::Configurator.create_missing_clone_dirs
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.error_message(name, errors)
|
14
|
+
#TODO: it is contingent whether solution is to fix errors using 'edit' command
|
15
|
+
"Module '#{name}' has errors:\n #{errors.to_s}\nYou can fix errors in the DSL by invoking the 'edit' command.\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# Method will trigger import for each missing module component
|
20
|
+
#
|
21
|
+
def trigger_module_component_import(missing_component_list,opts={})
|
22
|
+
puts "Auto-importing missing component module(s)"
|
23
|
+
|
24
|
+
missing_component_list.each do |m_module|
|
25
|
+
print "Importing component module '#{m_module['name']}' ... "
|
26
|
+
module_name = "#{m_module['namespace']}/#{m_module['name']}"
|
27
|
+
module_name += "/#{m_module['version']}" if m_module['version']
|
28
|
+
new_context_params = ::DTK::Shell::ContextParams.new([module_name])
|
29
|
+
new_context_params.override_method_argument!('option_2', m_module['version'])
|
30
|
+
new_context_params.forward_options( { "skip_cloning" => true}).merge!(opts)
|
31
|
+
|
32
|
+
response = ContextRouter.routeTask("component_module", "install", new_context_params, @conn)
|
33
|
+
puts(response.data(:does_not_exist) ? response.data(:does_not_exist) : "Done.")
|
34
|
+
raise DTK::Client::DtkError, response.error_message unless response.ok?
|
35
|
+
end
|
36
|
+
|
37
|
+
Response::Ok.new()
|
38
|
+
end
|
39
|
+
|
40
|
+
def resolve_missing_components(service_module_id, service_module_name, namespace_to_use, force_clone=false)
|
41
|
+
# Get dependency component modules and cross reference them with local component modules
|
42
|
+
module_component_list = post rest_url("service_module/list_component_modules"), { :service_module_id => service_module_id }
|
43
|
+
local_modules, needed_modules = OsUtil.local_component_module_list(), Array.new
|
44
|
+
|
45
|
+
module_component_list.data.each do |dependency_module|
|
46
|
+
unless local_modules.include?(formated_name = formulate_module_name(dependency_module['display_name'], dependency_module['version']))
|
47
|
+
needed_modules << dependency_module.merge({'formated_name' => formated_name})
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
unless needed_modules.empty?
|
52
|
+
puts "Service '#{service_module_name}' has following dependencies: \n\n"
|
53
|
+
needed_modules.each { |m| puts " - #{m['formated_name']}" }
|
54
|
+
is_install_dependencies = true
|
55
|
+
is_install_dependencies = Console.confirmation_prompt("\nDo you want to clone missing component module dependencies") unless force_clone
|
56
|
+
|
57
|
+
# we get list of modules available on server
|
58
|
+
|
59
|
+
new_context_params = nil
|
60
|
+
|
61
|
+
if is_install_dependencies
|
62
|
+
needed_modules.each do |m|
|
63
|
+
formated_name = m['formated_name']
|
64
|
+
print "Cloning component module '#{formated_name}' from server ... "
|
65
|
+
thor_options = {}
|
66
|
+
thor_options["version"] = m['version']
|
67
|
+
thor_options["skip_edit"] = true
|
68
|
+
thor_options["omit_output"] = true
|
69
|
+
new_context_params = ::DTK::Shell::ContextParams.new
|
70
|
+
new_context_params.forward_options(thor_options)
|
71
|
+
new_context_params.add_context_to_params(formated_name, :"component-module", m['id'])
|
72
|
+
response = ContextRouter.routeTask("component_module", "clone", new_context_params, @conn)
|
73
|
+
puts "Done."
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
#
|
81
|
+
# As the result we can have multiple version so we need to resolve them
|
82
|
+
#
|
83
|
+
# Returns: Array<String>
|
84
|
+
def resolve_module_names(e)
|
85
|
+
versions = (e['version'] ? e['version'].split(',') : ['CURRENT'])
|
86
|
+
|
87
|
+
versions.collect { |version| formulate_module_name(e['display_name'], version)}
|
88
|
+
end
|
89
|
+
|
90
|
+
# Resolves local module name
|
91
|
+
#
|
92
|
+
# Returns: String
|
93
|
+
def formulate_module_name(display_name, version)
|
94
|
+
version = nil if 'CURRENT'.eql?(version)
|
95
|
+
(version ? "#{display_name}-#{version.strip}" : "#{display_name}")
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module DTK; module Client; class CommandHelper
|
2
|
+
class ServiceLink < self; class << self
|
3
|
+
def post_body_with_id_keys(context_params,method_argument_names)
|
4
|
+
assembly_or_workspace_id = context_params.retrieve_arguments([[:service_id!,:workspace_id!]])
|
5
|
+
ret = {:assembly_id => assembly_or_workspace_id}
|
6
|
+
if context_params.is_last_command_eql_to?(:component)
|
7
|
+
component_id,service_type = context_params.retrieve_arguments([:component_id!,:option_1!],method_argument_names)
|
8
|
+
ret.merge(:input_component_id => component_id,:service_type => service_type)
|
9
|
+
else
|
10
|
+
service_link_id = context_params.retrieve_arguments([:option_1!],method_argument_names)
|
11
|
+
ret.merge(:service_link_id => service_link_id)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end; end
|
16
|
+
end; end; end
|
17
|
+
|
18
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module DTK; module Client
|
2
|
+
class SshProcessing
|
3
|
+
def self.update_ssh_known_hosts(server_dns,server_fingerprint)
|
4
|
+
known_hosts_path = ssh_known_hosts_path()
|
5
|
+
if File.file?(known_hosts_path)
|
6
|
+
`ssh-keygen -f #{known_hosts_path} -R #{server_dns}`
|
7
|
+
File.open(known_hosts_path,"a"){|f|f << server_fingerprint}
|
8
|
+
else
|
9
|
+
ssh_base_dir = ssh_base_dir()
|
10
|
+
unless File.directory?(ssh_base_dir)
|
11
|
+
Dir.mkdir(ssh_base_dir)
|
12
|
+
end
|
13
|
+
File.open(known_hosts_path,"w"){|f|f << server_fingerprint}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
def self.default_rsa_pub_key_path()
|
17
|
+
"#{ssh_base_dir()}/id_rsa.pub"
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.rsa_pub_key_content()
|
21
|
+
path_to_key = self.default_rsa_pub_key_path()
|
22
|
+
unless File.file?(path_to_key)
|
23
|
+
raise DtkError,"No File found at (#{path_to_key}). Path is wrong or it is necessary to generate the public rsa key (e.g., run ssh-keygen -t rsa)"
|
24
|
+
end
|
25
|
+
|
26
|
+
content = File.open(path_to_key){ |f| f.read }
|
27
|
+
content.chomp
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
private
|
32
|
+
def self.ssh_base_dir()
|
33
|
+
"#{ENV['HOME']}/.ssh" #TODO: very brittle
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.ssh_known_hosts_path()
|
37
|
+
"#{ssh_base_dir()}/known_hosts"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end; end
|
41
|
+
|
42
|
+
|
43
|
+
|