dtk-client 0.7.1 → 0.7.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d6d5f969664f0353c5a8389cb2ff93c540eb3e69
4
- data.tar.gz: e7161714340eceba543449faceaeed05244c96f6
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YzU5NzQ4MDE1NmNlMTU2NmViZWNkODkzMzRjOTMzMWVmMDI3MmVkZQ==
5
+ data.tar.gz: !binary |-
6
+ NDJjZDIyMmVkYjY2ZDdlOGY2ZjY1ODljYWI2YzBhMDA1NzVjMDUyNQ==
5
7
  SHA512:
6
- metadata.gz: 84773c714f5c6ec8b62c6fe5e3d3aebdd26a75097864e2be1caa5fd217a142109f3ce82a7f0b085182ffcf6de58ad39460504e2e890ddc2b1fab037bccd51427
7
- data.tar.gz: bad5dfff733069e5538294cc04910251bfcdd8fbbade2e60fe73a479737100cf070f42d9f2e2c7ea7661ca6c1c879c048fb3cea7221a02f870f11ddc21e4b1a4
8
+ metadata.gz: !binary |-
9
+ NmZjOWE0YmRlZjVkY2M0YThlNDUzMzc1NTA0MGIxOTQxMDQwZTdjM2ZmNWFk
10
+ MzRiMDVlZTBmZjUwODhlYjE5NjNlYTE0OTZmMGRhMDNmNDYzM2Y0YTkxMTc5
11
+ NTY4MmU3NmFmNzhmNjVkYzY1NjY2MTBmZTQ0Y2M3OTlmY2IxMzM=
12
+ data.tar.gz: !binary |-
13
+ ZDllMmIyYjQ2NGMyY2ZlYzc4MDM2Y2M5YzM1MTI1MmE0NTYyOTljOGY2YmRl
14
+ ODRlYzg5ZTM4MTVjNWNmODI3ODNlZTgxNWU2ZWJkMzQ0ODVhZGViYjYzNzE1
15
+ MjUyMDAyNGViNjkyMWY1YjI2M2YwNjBmYjdjM2I1OWE3MWY0OGQ=
data/bin/dtk-execute ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path('../lib/client', File.dirname(__FILE__))
4
+ require File.expand_path('../lib/execute', File.dirname(__FILE__))
5
+ require File.expand_path('../lib/configurator', File.dirname(__FILE__))
6
+
7
+ include DTK::Client
8
+
9
+ Configurator.check_config_exists
10
+
11
+ # if connection parameters are not set up properly, print warning and exit dtk_shell
12
+ conn = Session.get_connection()
13
+ exit if validate_connection(conn)
14
+
15
+ require 'optparse'
16
+ banner = "Usage: dtk-execute add-tenant TENANT-NAME"
17
+ tenant_name = nil
18
+ if ARGV.size == 2
19
+ if ARGV[0] == 'add-tenant'
20
+ tenant_name = ARGV[1]
21
+ end
22
+ end
23
+ unless tenant_name
24
+ # forces usage then exit
25
+ ARGV[0] = '--help'
26
+ end
27
+ options = {}
28
+ OptionParser.new do |opts|
29
+ opts.banner = banner
30
+ end.parse!
31
+
32
+ Execute.add_tenant(tenant_name)
data/dtk-client.gemspec CHANGED
@@ -22,14 +22,14 @@ Gem::Specification.new do |gem|
22
22
  gem.require_paths = ["lib"]
23
23
  gem.version = "#{DtkClient::VERSION}.#{ARGV[3]}".chomp(".")
24
24
 
25
+ gem.add_dependency 'mime-types','~> 1.25'
25
26
  gem.add_dependency 'bundler','>= 1.2.4'
26
27
  gem.add_dependency 'json_pure' ,'1.7.4'
27
28
  gem.add_dependency 'diff-lcs','1.1.3'
28
- gem.add_dependency 'mime-types','~> 1.25'
29
29
  gem.add_dependency 'hirb','~> 0.7.0'
30
30
  gem.add_dependency 'thor','~> 0.15.4'
31
31
  gem.add_dependency 'erubis','~> 2.7.0'
32
- gem.add_dependency 'dtk-common-core','0.7.0'
32
+ gem.add_dependency 'dtk-common-core','0.7.0.1'
33
33
  gem.add_dependency 'git','~> 1.2.6'
34
34
  gem.add_dependency 'colorize','~> 0.5.8'
35
35
  gem.add_dependency 'highline', '1.6.16'
@@ -9,6 +9,8 @@ dtk_require_common_commands('thor/set_required_params')
9
9
  dtk_require_common_commands('thor/edit')
10
10
  dtk_require_common_commands('thor/purge_clone')
11
11
  dtk_require_common_commands('thor/list_diffs')
12
+ dtk_require_common_commands('thor/action_result_handler')
13
+
12
14
  LOG_SLEEP_TIME_W = DTK::Configuration.get(:tail_log_frequency)
13
15
 
14
16
  module DTK::Client
@@ -110,7 +112,18 @@ module DTK::Client
110
112
  end
111
113
 
112
114
  def converge_aux(context_params)
113
- assembly_or_workspace_id = context_params.retrieve_arguments([REQ_ASSEMBLY_OR_WS_ID],method_argument_names)
115
+ assembly_or_workspace_id,task_action,task_params_string = context_params.retrieve_arguments([REQ_ASSEMBLY_OR_WS_ID,:option_1,:option_2],method_argument_names)
116
+
117
+ task_params = nil
118
+ if task_params_string
119
+ task_params = task_params_string.split(',').inject(Hash.new) do |h,av|
120
+ av_split = av.split('=')
121
+ unless av_split.size == 2
122
+ raise DTK::Client::DtkValidationError, "The task parameters (#{task_params_string}) is ill-formed"
123
+ end
124
+ h.merge(av_split[0] => av_split[1])
125
+ end
126
+ end
114
127
 
115
128
  post_body = {
116
129
  :assembly_id => assembly_or_workspace_id
@@ -126,6 +139,8 @@ module DTK::Client
126
139
  end
127
140
 
128
141
  post_body.merge!(:commit_msg => options.commit_msg) if options.commit_msg
142
+ post_body.merge!(:task_action => task_action) if task_action
143
+ post_body.merge!(:task_params => task_params) if task_params
129
144
 
130
145
  response = post rest_url("assembly/create_task"), post_body
131
146
  return response unless response.ok?
@@ -590,6 +605,61 @@ module DTK::Client
590
605
  response
591
606
  end
592
607
 
608
+ def grant_access_aux(context_params)
609
+ service_id, system_user, rsa_key_name, path_to_rsa_pub_key = context_params.retrieve_arguments([REQ_ASSEMBLY_OR_WS_ID, :option_1!, :option_2!, :option_3],method_argument_names)
610
+
611
+ path_to_rsa_pub_key ||= SSHUtil.default_rsa_pub_key_path()
612
+ rsa_pub_key_content = SSHUtil.read_and_validate_pub_key(path_to_rsa_pub_key)
613
+
614
+ response = post_file rest_url("assembly/initiate_ssh_pub_access"), {
615
+ :agent_action => :grant_access,
616
+ :system_user => system_user,
617
+ :rsa_pub_name => rsa_key_name,
618
+ :rsa_pub_key => rsa_pub_key_content,
619
+ :assembly_id => service_id,
620
+ :target_nodes => options.nodes
621
+ }
622
+
623
+ return response unless response.ok?
624
+
625
+ action_results_id = response.data(:action_results_id)
626
+
627
+ print_action_results(action_results_id)
628
+
629
+ nil
630
+ end
631
+
632
+ def revoke_access_aux(context_params)
633
+ service_id, system_user, rsa_key_name = context_params.retrieve_arguments([REQ_ASSEMBLY_OR_WS_ID, :option_1!, :option_2!],method_argument_names)
634
+
635
+ response = post_file rest_url("assembly/initiate_ssh_pub_access"), {
636
+ :agent_action => :revoke_access,
637
+ :system_user => system_user,
638
+ :rsa_pub_name => rsa_key_name,
639
+ :assembly_id => service_id,
640
+ :target_nodes => options.nodes
641
+ }
642
+
643
+ return response unless response.ok?
644
+
645
+ action_results_id = response.data(:action_results_id)
646
+
647
+ print_action_results(action_results_id)
648
+
649
+ nil
650
+ end
651
+
652
+ def list_ssh_access_aux(context_params)
653
+ service_id = context_params.retrieve_arguments([REQ_ASSEMBLY_OR_WS_ID],method_argument_names)
654
+
655
+ response = post_file rest_url("assembly/list_ssh_access"), {
656
+ :assembly_id => service_id
657
+ }
658
+
659
+ response.render_table(:ssh_access)
660
+ response
661
+ end
662
+
593
663
  def set_target_aux(context_params)
594
664
  assembly_or_workspace_id, target_id = context_params.retrieve_arguments([REQ_ASSEMBLY_OR_WS_ID,:option_1!],method_argument_names)
595
665
  post_body = {
@@ -738,7 +808,22 @@ module DTK::Client
738
808
  :node_id => node_id
739
809
  }
740
810
  response = post(rest_url("assembly/delete_node"),post_body)
741
- # @@invalidate_map << :assembly_node
811
+ response
812
+ end
813
+
814
+ def delete_node_group_aux(context_params)
815
+ assembly_or_workspace_id, node_id = context_params.retrieve_arguments([REQ_ASSEMBLY_OR_WS_ID,:option_1!],method_argument_names)
816
+
817
+ unless options.force?
818
+ what = "node"
819
+ return unless Console.confirmation_prompt("Are you sure you want to delete and destroy #{what} '#{node_id}'"+'?')
820
+ end
821
+
822
+ post_body = {
823
+ :assembly_id => assembly_or_workspace_id,
824
+ :node_id => node_id
825
+ }
826
+ response = post(rest_url("assembly/delete_node_group"),post_body)
742
827
  response
743
828
  end
744
829
 
@@ -89,8 +89,11 @@ module DTK::Client
89
89
  },
90
90
  :delete_node => {
91
91
  :endpoint => "assembly",
92
- :url => "assembly/info_about",
93
- :opts => {:subtype=>"instance", :about=>"nodes"}
92
+ :url => "assembly/get_nodes_without_node_groups"
93
+ },
94
+ :delete_node_group => {
95
+ :endpoint => "assembly",
96
+ :url => "assembly/get_node_groups"
94
97
  }
95
98
  }
96
99
  }
@@ -236,6 +239,8 @@ module DTK::Client
236
239
  Response::Ok.new()
237
240
  end
238
241
 
242
+ # TODO: DTK-1986 introduces the hidden optional terms [WORKFLOW-ACTION [WORKFLOW-PARAMS]]
243
+ # desc "SERVICE-NAME/ID converge [-m COMMIT-MSG] [WORKFLOW-ACTION [WORKFLOW-PARAMS]]", "Converge service instance."
239
244
  desc "SERVICE-NAME/ID converge [-m COMMIT-MSG]", "Converge service instance."
240
245
  method_option "commit_msg",:aliases => "-m" ,
241
246
  :type => :string,
@@ -479,64 +484,20 @@ TODO: will put in dot release and will rename to 'extend'
479
484
  desc "SERVICE-NAME/ID grant-access USER-ACCOUNT PUB-KEY-NAME [PATH-TO-PUB-KEY] [--nodes NODE-NAMES]", "Grants ssh access to user account USER-ACCOUNT for nodes in service instance"
480
485
  method_option :nodes, :type => :string, :default => nil
481
486
  def grant_access(context_params)
482
- service_id, system_user, rsa_key_name, path_to_rsa_pub_key = context_params.retrieve_arguments([:service_id!,:option_1!, :option_2!, :option_3],method_argument_names)
483
-
484
- path_to_rsa_pub_key ||= SSHUtil.default_rsa_pub_key_path()
485
- rsa_pub_key_content = SSHUtil.read_and_validate_pub_key(path_to_rsa_pub_key)
486
-
487
- response = post_file rest_url("assembly/initiate_ssh_pub_access"), {
488
- :agent_action => :grant_access,
489
- :system_user => system_user,
490
- :rsa_pub_name => rsa_key_name,
491
- :rsa_pub_key => rsa_pub_key_content,
492
- :assembly_id => service_id,
493
- :target_nodes => options.nodes
494
- }
495
-
496
- return response unless response.ok?
497
-
498
- action_results_id = response.data(:action_results_id)
499
-
500
- print_action_results(action_results_id)
501
-
502
- nil
487
+ grant_access_aux(context_params)
503
488
  end
504
489
 
505
490
  desc "SERVICE-NAME/ID revoke-access USER-ACCOUNT PUB-KEY-NAME [PATH-TO-PUB-KEY] [--nodes NODE-NAMES]", "Revokes ssh access to user account USER-ACCOUNT for nodes in service instance"
506
491
  method_option :nodes, :type => :string, :default => nil
507
492
  def revoke_access(context_params)
508
- service_id, system_user, rsa_key_name = context_params.retrieve_arguments([:service_id!,:option_1!, :option_2!],method_argument_names)
509
-
510
- response = post_file rest_url("assembly/initiate_ssh_pub_access"), {
511
- :agent_action => :revoke_access,
512
- :system_user => system_user,
513
- :rsa_pub_name => rsa_key_name,
514
- :assembly_id => service_id,
515
- :target_nodes => options.nodes
516
- }
517
-
518
- return response unless response.ok?
519
-
520
- action_results_id = response.data(:action_results_id)
521
-
522
- print_action_results(action_results_id)
523
-
524
- nil
493
+ revoke_access_aux(context_params)
525
494
  end
526
495
 
527
496
  desc "SERVICE-NAME/ID list-ssh-access", "List SSH access for each of the nodes"
528
497
  def list_ssh_access(context_params)
529
- service_id = context_params.retrieve_arguments([:service_id!],method_argument_names)
530
-
531
- response = post_file rest_url("assembly/list_ssh_access"), {
532
- :assembly_id => service_id
533
- }
534
-
535
- response.render_table(:ssh_access)
536
- response
498
+ list_ssh_access_aux(context_params)
537
499
  end
538
500
 
539
-
540
501
  desc "SERVICE-NAME/ID info", "Get info about content of the service."
541
502
  def info(context_params)
542
503
  info_aux(context_params)
@@ -672,6 +633,21 @@ TODO: will put in dot release and will rename to 'extend'
672
633
  return response
673
634
  end
674
635
 
636
+ desc "SERVICE-NAME/ID delete-node-group ^^NODE-NAME [-y]","Delete node group and all nodes that are part of that group."
637
+ method_option :force, :aliases => '-y', :type => :boolean, :default => false
638
+ def delete_node_group(context_params)
639
+ response = delete_node_group_aux(context_params)
640
+
641
+ @@invalidate_map << :assembly
642
+ @@invalidate_map << :assembly_node
643
+ @@invalidate_map << :service
644
+ @@invalidate_map << :service_node
645
+ @@invalidate_map << :workspace
646
+ @@invalidate_map << :workspace_node
647
+
648
+ return response
649
+ end
650
+
675
651
  desc "HIDE_FROM_BASE delete NAME/ID [-y]","Delete node, terminating it if the node has been spun up."
676
652
  def delete(context_params)
677
653
  if context_params.is_last_command_eql_to?(:node)
@@ -8,6 +8,7 @@ dtk_require_common_commands('thor/task_status')
8
8
  dtk_require_common_commands('thor/edit')
9
9
  dtk_require_common_commands('thor/purge_clone')
10
10
  dtk_require_common_commands('thor/assembly_workspace')
11
+ dtk_require_common_commands('thor/action_result_handler')
11
12
  # LOG_SLEEP_TIME_W = DTK::Configuration.get(:tail_log_frequency)
12
13
 
13
14
  module DTK::Client
@@ -18,6 +19,7 @@ module DTK::Client
18
19
  include EditMixin
19
20
  include PurgeCloneMixin
20
21
  include AssemblyWorkspaceMixin
22
+ include ActionResultHandler
21
23
 
22
24
  def get_workspace_name(workspace_id)
23
25
  get_name_from_id_helper(workspace_id)
@@ -65,8 +67,11 @@ module DTK::Client
65
67
  },
66
68
  :delete_node => {
67
69
  :endpoint => "assembly",
68
- :url => "assembly/info_about",
69
- :opts => {:subtype=>"instance", :about=>"nodes"}
70
+ :url => "assembly/get_nodes_without_node_groups"
71
+ },
72
+ :delete_node_group => {
73
+ :endpoint => "assembly",
74
+ :url => "assembly/get_node_groups"
70
75
  }
71
76
  }
72
77
  }
@@ -336,6 +341,21 @@ module DTK::Client
336
341
  return response
337
342
  end
338
343
 
344
+ desc "WORKSPACE-NAME/ID delete-node-group ^^NODE-NAME [-y]","Delete node group and all nodes that are part of that group."
345
+ method_option :force, :aliases => '-y', :type => :boolean, :default => false
346
+ def delete_node_group(context_params)
347
+ response = delete_node_group_aux(context_params)
348
+
349
+ @@invalidate_map << :assembly
350
+ @@invalidate_map << :assembly_node
351
+ @@invalidate_map << :service
352
+ @@invalidate_map << :service_node
353
+ @@invalidate_map << :workspace
354
+ @@invalidate_map << :workspace_node
355
+
356
+ return response
357
+ end
358
+
339
359
  desc "WORKSPACE-NAME/ID unlink-components TARGET-CMP-NAME SOURCE-CMP-NAME [DEPENDENCY-NAME]", "Remove a component link."
340
360
  def unlink_components(context_params)
341
361
  unlink_components_aux(context_params)
@@ -383,6 +403,23 @@ module DTK::Client
383
403
  def grep(context_params)
384
404
  grep_aux(context_params)
385
405
  end
406
+
407
+ desc "WORKSPACE-NAME/ID grant-access USER-ACCOUNT PUB-KEY-NAME [PATH-TO-PUB-KEY] [--nodes NODE-NAMES]", "Grants ssh access to user account USER-ACCOUNT for nodes in workspace"
408
+ method_option :nodes, :type => :string, :default => nil
409
+ def grant_access(context_params)
410
+ grant_access_aux(context_params)
411
+ end
412
+
413
+ desc "WORKSPACE-NAME/ID revoke-access USER-ACCOUNT PUB-KEY-NAME [PATH-TO-PUB-KEY] [--nodes NODE-NAMES]", "Revokes ssh access to user account USER-ACCOUNT for nodes in workspace"
414
+ method_option :nodes, :type => :string, :default => nil
415
+ def revoke_access(context_params)
416
+ revoke_access_aux(context_params)
417
+ end
418
+
419
+ desc "WORKSPACE-NAME/ID list-ssh-access", "List SSH access for each of the nodes"
420
+ def list_ssh_access(context_params)
421
+ list_ssh_access_aux(context_params)
422
+ end
386
423
 
387
424
  desc "WORKSPACE-NAME/ID info", "Get info about content of the workspace."
388
425
  def info(context_params)
@@ -450,6 +487,11 @@ module DTK::Client
450
487
  list_violations_aux(context_params)
451
488
  end
452
489
 
490
+ desc "WORKSPACE-NAME/ID print-includes", "Finds includes in the workspace."
491
+ def print_includes(context_params)
492
+ print_includes_aux(context_params)
493
+ end
494
+
453
495
  desc "WORKSPACE-NAME/ID purge [-y]", "Purge the workspace, deleting and terminating any nodes that have been spun up."
454
496
  method_option :force, :aliases => '-y', :type => :boolean, :default => false
455
497
  def purge(context_params)
data/lib/core.rb CHANGED
@@ -469,10 +469,10 @@ module DTK
469
469
  # In development mode we want bigger timeout allowing us to debbug on server while still
470
470
  # keeping connection alive and receivinga response
471
471
  if ::DTK::Configuration.get(:development_mode)
472
- DefaultRestOpts = {:timeout => 2000, :open_timeout => 2, :error_response_class => Client::Response::Error}
472
+ DefaultRestOpts = {:timeout => 2000, :open_timeout => 10, :error_response_class => Client::Response::Error}
473
473
  # DefaultRestOpts = {:timeout => 50, :open_timeout => 2, :error_response_class => Client::Response::Error}
474
474
  else
475
- DefaultRestOpts = {:timeout => 100, :open_timeout => 1, :error_response_class => Client::Response::Error}
475
+ DefaultRestOpts = {:timeout => 100, :open_timeout => 10, :error_response_class => Client::Response::Error}
476
476
  end
477
477
 
478
478
  # enable SSL verification
@@ -1,3 +1,3 @@
1
1
  module DtkClient
2
- VERSION="0.7.1"
2
+ VERSION="0.7.1.1"
3
3
  end
@@ -0,0 +1,43 @@
1
+ class DTK::Client::Execute
2
+ class Command::APICall
3
+ class Map < Hash
4
+ def initialize(hash={})
5
+ super()
6
+ replace(hash)
7
+ end
8
+
9
+ def translate(api_params={},opts={})
10
+ if Rest::Post.matches?(type())
11
+ Command::RestCall::Post.new(:path => path(),:body => translate_to_rest_body(api_params,opts))
12
+ else
13
+ raise "Type in following map is not defined not defined: #{self.inspect}"
14
+ end
15
+ end
16
+
17
+ private
18
+ def translate_to_rest_body(api_params,opts)
19
+ body().inject(Hash.new) do |h,(k,v)|
20
+ # if TranslationTerm.matches is false then v is a constant
21
+ processed_v =
22
+ if TranslationTerm.matches?(v)
23
+ v.instance_form().translate(k,api_params,opts)
24
+ else
25
+ v
26
+ end
27
+ h.merge(k => processed_v)
28
+ end
29
+ end
30
+
31
+ def type()
32
+ self[:type]
33
+ end
34
+ def path()
35
+ self[:path]
36
+ end
37
+ def body()
38
+ self[:body]
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,73 @@
1
+ class DTK::Client::Execute
2
+ class Command::APICall
3
+ class Service < self
4
+ def self.object_type()
5
+ :service
6
+ end
7
+
8
+ CommandMap = {
9
+ :add_component => Map.new(
10
+ :type => Rest::Post,
11
+ :path => 'assembly/add_component',
12
+ :body => {
13
+ :assembly_id => Required(:service),
14
+ :subtype => 'instance',
15
+ :node_id => Required(:node),
16
+ :component_template_id => Required(:component),
17
+ :idempotent => Equal::OrDefault(true),
18
+ :donot_update_workflow => Equal::OrDefault(false)
19
+ }
20
+ ),
21
+
22
+ :set_attribute => Map.new(
23
+ :type => Rest::Post,
24
+ :path => 'assembly/set_attributes',
25
+ :body => {
26
+ :assembly_id => Required(:service),
27
+ :pattern => Required(:attribute_path),
28
+ # TODO: support FN
29
+ # :pattern => FN{"#{Required(:node)}/#{Required(:component)}/#{Required(:attribute)}"
30
+ :value => Required::Equal
31
+ }
32
+ ),
33
+
34
+ :link_components => Map.new(
35
+ :type => Rest::Post,
36
+ :path => 'assembly/add_service_link',
37
+ :body => {
38
+ :assembly_id => Required(:service),
39
+ :input_component_id => Required(:input_component),
40
+ :output_component_id => Required(:output_component),
41
+ }
42
+ ),
43
+
44
+ :execute_workflow =>
45
+ [
46
+ Map.new(
47
+ :type => Rest::Post,
48
+ :path => 'assembly/create_task',
49
+ :body => {
50
+ :assembly_id => Required(:service),
51
+ :task_action => Required(:workflow_name),
52
+ :task_params => Required(:workflow_params)
53
+ }
54
+ ),
55
+ Map.new(
56
+ :type => Rest::Post,
57
+ :path => 'task/execute',
58
+ :body => {
59
+ :task_id => PreviousResponse(:task_id)
60
+ }
61
+ )]
62
+ }
63
+
64
+ module CustomMapping
65
+ # example would be
66
+ # def self.command(params)
67
+ # ...
68
+ # end
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,103 @@
1
+ class DTK::Client::Execute
2
+ class Command::APICall
3
+
4
+ # abstract classes
5
+ class TranslationTerm
6
+ def self.matches?(obj)
7
+ obj.kind_of?(self) or
8
+ (obj.kind_of?(Class) and obj <= self)
9
+ end
10
+
11
+ def self.instance_form()
12
+ new()
13
+ end
14
+ def instance_form()
15
+ self
16
+ end
17
+
18
+ class Operation < self
19
+ end
20
+
21
+ class Param < self
22
+ private
23
+ def index(api_params,key)
24
+ api_params[key]
25
+ end
26
+
27
+ def index_required(api_params,key)
28
+ unless has_key?(api_params,key)
29
+ raise ErrorUsage.new("Missing key '#{key}' in params: #{api_params.inspect}")
30
+ end
31
+ index(api_params,key)
32
+ end
33
+
34
+ def has_key?(api_params,key)
35
+ api_params.has_key?(key)
36
+ end
37
+
38
+ end
39
+ end
40
+
41
+ # concrete classes
42
+
43
+ class Rest < TranslationTerm::Operation
44
+ class Post < self
45
+ end
46
+ end
47
+
48
+ class Required < TranslationTerm::Param
49
+ def initialize(input_key=nil)
50
+ @input = input_key
51
+ end
52
+
53
+ def translate(key,api_params,opts={})
54
+ index_required(api_params,@input||key)
55
+ end
56
+
57
+ class Equal < self
58
+ end
59
+ end
60
+
61
+ class Equal < TranslationTerm::Param
62
+ def translate(key,api_params,opts={})
63
+ index(api_params,key)
64
+ end
65
+
66
+ class Required < self
67
+ def translate(key,api_params,opts={})
68
+ index_required(api_params,key)
69
+ end
70
+ end
71
+
72
+ def self.OrDefault(default_value)
73
+ OrDefault.new(default_value)
74
+ end
75
+
76
+ class OrDefault < self
77
+ def initialize(default_value)
78
+ @default_value = default_value
79
+ end
80
+ def translate(key,api_params,opts={})
81
+ has_key?(api_params,key) ? index(api_params,key) : @default_value
82
+ end
83
+ end
84
+ end
85
+
86
+ class PreviousResponse < TranslationTerm::Param
87
+ def initialize(response_key)
88
+ @response_key = response_key
89
+ end
90
+ def translate(key,api_params,opts={})
91
+ unless last_result = opts[:last_result]
92
+ raise ErrorUsage.new("PreviousResponse used before results computed")
93
+ end
94
+ match = nil
95
+ unless matching_key = [@response_key.to_s,@response_key.to_sym].find{|k|last_result.has_key?(k)}
96
+ raise ErrorUsage.new("Key #{@response_key} in PreviousResponse not found in last results (#{last_result.inspect})")
97
+ end
98
+ last_result[matching_key]
99
+ end
100
+ end
101
+ end
102
+ end
103
+
@@ -0,0 +1,43 @@
1
+ class DTK::Client::Execute
2
+ class Command
3
+ class APICall < self
4
+
5
+ # order matters; having these defs before requires; plus order of these requires
6
+ def self.Required(key)
7
+ Required.new(key)
8
+ end
9
+ def self.PreviousResponse(response_key)
10
+ PreviousResponse.new(response_key)
11
+ end
12
+ dtk_require('api_call/translation_term')
13
+ dtk_require('api_call/map')
14
+ dtk_require('api_call/service')
15
+
16
+
17
+ # calss block where on one or more commands that achieve the api
18
+ def raw_executable_commands(&block)
19
+ method = required(:method).to_sym
20
+ case required(:object_type).to_sym
21
+ when :service
22
+ Service.raw_executable_commands(method,&block)
23
+ else
24
+ raise ErrorUsage.new("The object_type '#{object_type}' is not supported")
25
+ end
26
+ end
27
+
28
+ private
29
+ def self.raw_executable_commands(method,&block)
30
+ if command_map = self::CommandMap[method]
31
+ array_form(command_map).each{|raw_command|block.call(raw_command)}
32
+ else
33
+ raise ErrorUsage.new("The method on '#{method}' on object type '#{object_type()}' is not supported")
34
+ end
35
+ end
36
+
37
+ def self.array_form(obj)
38
+ obj.kind_of?(Array) ? obj : [obj]
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ class DTK::Client::Execute
2
+ class Command
3
+ class RestCall < self
4
+ # TODO: allow calls like 'converge' which is a macro; we either directly support or have a sub class of RestCall called macro
5
+ attr_reader :path
6
+ def initialize(hash)
7
+ super
8
+ @path = required(:path)
9
+ end
10
+
11
+ class Post < self
12
+ attr_reader :body
13
+ def initialize(hash)
14
+ super
15
+ @body = optional?(:body)||{}
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ class DTK::Client::Execute
2
+ class Command
3
+ dtk_require('command/rest_call')
4
+ dtk_require('command/api_call')
5
+
6
+ attr_reader :result_var,:input_hash
7
+ def initialize(input_hash)
8
+ @input_hash = input_hash
9
+ @result_var = optional?(:result_var)
10
+ end
11
+
12
+ private
13
+ def required(key)
14
+ unless @input_hash.has_key?(key)
15
+ raise ErrorUsage.new("Missing required key '#{key}' in: #{@input_hash.inspect}")
16
+ end
17
+ @input_hash[key]
18
+ end
19
+ def optional?(key)
20
+ @input_hash[key]
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,43 @@
1
+ class DTK::Client::Execute; class CommandProcessor
2
+ class RestCall< self
3
+ extend ::DTK::Client::CommandBase # TODO: have a Base that is not just for commands (CommandBase)
4
+
5
+ def self.execute(rest_command)
6
+ response = raw_execute(rest_command)
7
+ if response.ok?
8
+ response.data
9
+ else
10
+ raise Error.new(response,rest_command)
11
+ end
12
+ end
13
+
14
+ private
15
+ def self.raw_execute(rest_command)
16
+ if rest_command.kind_of?(Command::RestCall::Post)
17
+ post(rest_url(rest_command.path),rest_command.body)
18
+ else
19
+ raise ErrorUsage.new("Unexpected Rest Command type: #{rest_command.class}")
20
+ end
21
+ end
22
+
23
+ class Error < ErrorUsage
24
+ def initialize(response_not_ok,rest_command)
25
+ error_print_form = error_print_form(response_not_ok)
26
+ error_msg = "Bad Rest response from call (#{rest_command.input_hash.inspect}:\n #{error_print_form}"
27
+ super(error_msg)
28
+ end
29
+ private
30
+ def error_print_form(response_not_ok)
31
+ ret_obj =
32
+ if errors = response_not_ok['errors']
33
+ errors.size == 1 ? errors.first : errors
34
+ else
35
+ response_not_ok
36
+ end
37
+ ret_obj.kind_of?(String) ? ret_obj : ret_obj.inspect
38
+ end
39
+ end
40
+
41
+ end
42
+ end; end
43
+
@@ -0,0 +1,13 @@
1
+ class DTK::Client::Execute
2
+ class CommandProcessor
3
+ dtk_require('command_processor/rest_call')
4
+
5
+ def self.execute(command)
6
+ if command.kind_of?(Command::RestCall)
7
+ RestCall.execute(command)
8
+ else
9
+ raise ErrorUsage.new("Unexpected Command type: #{command.class}")
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ class DTK::Client::Execute
2
+ class ErrorUsage < ::DTK::Client::Error
3
+ end
4
+ end
@@ -0,0 +1,42 @@
1
+ class DTK::Client::Execute
2
+
3
+ def self.add_tenant(tenant_name,params={})
4
+ component = "dtk_tenant[#{tenant_name}]"
5
+ service = 'dtkhost5'
6
+ node = 'server'
7
+ tenant_password = params[:tenant_password] || 'foo'
8
+ catalog_user_name = params[:catalog_user_name] || tenant_name
9
+
10
+ ExecuteContext(:print_results => true) do
11
+ result = call 'service/add_component',
12
+ :service => service,
13
+ :node => node,
14
+ :component => component,
15
+ :donot_update_workflow => true
16
+
17
+ result = call 'service/set_attribute',
18
+ :service => service,
19
+ :attribute_path => "#{node}/#{component}/tenant_password",
20
+ :value => tenant_password
21
+
22
+ result = call 'service/set_attribute',
23
+ :service => service,
24
+ :attribute_path => "#{node}/#{component}/catalog_user_name",
25
+ :value => catalog_user_name
26
+
27
+ ['dtk_postgresql::databases'].each do |shared_service_component|
28
+ result = call 'service/link_components',
29
+ :service => service,
30
+ :input_component => "#{node}/#{component}",
31
+ :output_component => "#{node}/#{shared_service_component}"
32
+ end
33
+
34
+ result = call 'service/execute_workflow',
35
+ :service => service,
36
+ :workflow_name => 'add_tenant',
37
+ :workflow_params => {'name' => tenant_name}
38
+
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,3 @@
1
+ class DTK::Client::Execute
2
+ dtk_require('examples/add_tenant')
3
+ end
@@ -0,0 +1,20 @@
1
+ class DTK::Client::Execute
2
+ class ExecuteContext
3
+ class ResultStore < Hash
4
+ def store(result,result_index=nil)
5
+ self[result_index||Index.last] = result
6
+ end
7
+
8
+ def get_last_result?()
9
+ self[Index.last]
10
+ end
11
+
12
+ module Index
13
+ def self.last()
14
+ Last
15
+ end
16
+ Last = :last
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,70 @@
1
+ class DTK::Client::Execute
2
+ class ExecuteContext
3
+ dtk_require('execute_context/result_store')
4
+
5
+ module ClassMixin
6
+ def ExecuteContext(opts={},&block)
7
+ ExecuteContext.new(opts).execute(&block)
8
+ end
9
+ end
10
+
11
+ def initialize(opts={})
12
+ @print_results = opts[:print_results]
13
+ @proxy = Proxy.new()
14
+ end
15
+
16
+ def execute(&block)
17
+ result, command = instance_eval(&block)
18
+ result
19
+ end
20
+
21
+ def method_missing(m, *args, &block)
22
+ result, command = @proxy.send(m, *args, &block)
23
+ if @print_results
24
+ pp(:command => command.input_hash(),:result => result)
25
+ end
26
+ [result, command]
27
+ end
28
+
29
+ # commands in the execute context
30
+ class Proxy
31
+ def initialize()
32
+ @result_store = ResultStore.new()
33
+ end
34
+
35
+ def call(object_type__method,params={})
36
+ object_type, method = split_object_type__method(object_type__method)
37
+ api_command = Command::APICall.new(:object_type => object_type, :method => method, :params => params)
38
+ result = nil
39
+ api_command.raw_executable_commands() do |raw_command|
40
+ last_result = @result_store.get_last_result?()
41
+ command = raw_command.translate(params,:last_result => last_result)
42
+ result = CommandProcessor.execute(command)
43
+ @result_store.store(result)
44
+ end
45
+ [result, api_command]
46
+ end
47
+
48
+ def post_rest_call(path,body={})
49
+ command = Command::RestCall::Post.new(:path => path, :body => body, :last_result => @last_result)
50
+ result = CommandProcessor.execute(command)
51
+ [result, command]
52
+ end
53
+
54
+ private
55
+ # returns [object_type, method]
56
+ def split_object_type__method(str)
57
+ DelimitersObjectTypeMethod.each do |d|
58
+ if str =~ Regexp.new("(^[^#{d}]+)#{d}([^#{d}]+$)")
59
+ return [$1,$2]
60
+ end
61
+ end
62
+ raise ErrorUsage.new("Illegal term '#{str}'")
63
+ end
64
+
65
+ DelimitersObjectTypeMethod = ['\/']
66
+ end
67
+
68
+ end
69
+ end
70
+
data/lib/execute.rb ADDED
@@ -0,0 +1,13 @@
1
+ module DTK::Client
2
+ class Execute
3
+ # The order matters
4
+ dtk_require('execute/error_usage')
5
+ dtk_require('execute/command')
6
+ dtk_require('execute/command_processor')
7
+ dtk_require('execute/execute_context')
8
+ dtk_require('execute/examples')
9
+
10
+ extend ExecuteContext::ClassMixin
11
+ end
12
+ end
13
+
data/lib/shell/context.rb CHANGED
@@ -7,6 +7,7 @@ module DTK
7
7
 
8
8
  class Context
9
9
  include DTK::Client::Auxiliary
10
+ include DTK::Client::CommandBase
10
11
 
11
12
  # client commands
12
13
  CLIENT_COMMANDS = ['cc','exit','clear','pushc','popc','dirs','help']
@@ -792,7 +793,9 @@ module DTK
792
793
  id = entity_name.identifier
793
794
  opts[id_label] = id
794
795
 
795
- response_ruby_obj = DTK::Client::CommandBaseThor.get_cached_response(endpoint.to_sym, url, opts)
796
+ # response_ruby_obj = DTK::Client::CommandBaseThor.get_cached_response(endpoint.to_sym, url, opts)
797
+ # when extended context autocomplete always send new request
798
+ response_ruby_obj = post rest_url(url), opts
796
799
  return [] if(response_ruby_obj.nil? || !response_ruby_obj.ok?)
797
800
 
798
801
  response_ruby_obj.data.each do |d|
metadata CHANGED
@@ -1,27 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dtk-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.7.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rich PELAVIN
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-12 00:00:00.000000000 Z
11
+ date: 2015-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mime-types
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.25'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.25'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
- - - ">="
31
+ - - ! '>='
18
32
  - !ruby/object:Gem::Version
19
33
  version: 1.2.4
20
34
  type: :runtime
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - ">="
38
+ - - ! '>='
25
39
  - !ruby/object:Gem::Version
26
40
  version: 1.2.4
27
41
  - !ruby/object:Gem::Dependency
@@ -52,60 +66,46 @@ dependencies:
52
66
  - - '='
53
67
  - !ruby/object:Gem::Version
54
68
  version: 1.1.3
55
- - !ruby/object:Gem::Dependency
56
- name: mime-types
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.25'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.25'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: hirb
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ~>
74
74
  - !ruby/object:Gem::Version
75
75
  version: 0.7.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ~>
81
81
  - !ruby/object:Gem::Version
82
82
  version: 0.7.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: thor
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ~>
88
88
  - !ruby/object:Gem::Version
89
89
  version: 0.15.4
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ~>
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.15.4
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: erubis
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - ~>
102
102
  - !ruby/object:Gem::Version
103
103
  version: 2.7.0
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
108
+ - - ~>
109
109
  - !ruby/object:Gem::Version
110
110
  version: 2.7.0
111
111
  - !ruby/object:Gem::Dependency
@@ -114,40 +114,40 @@ dependencies:
114
114
  requirements:
115
115
  - - '='
116
116
  - !ruby/object:Gem::Version
117
- version: 0.7.0
117
+ version: 0.7.0.1
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - '='
123
123
  - !ruby/object:Gem::Version
124
- version: 0.7.0
124
+ version: 0.7.0.1
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: git
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - "~>"
129
+ - - ~>
130
130
  - !ruby/object:Gem::Version
131
131
  version: 1.2.6
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - "~>"
136
+ - - ~>
137
137
  - !ruby/object:Gem::Version
138
138
  version: 1.2.6
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: colorize
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - "~>"
143
+ - - ~>
144
144
  - !ruby/object:Gem::Version
145
145
  version: 0.5.8
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - "~>"
150
+ - - ~>
151
151
  - !ruby/object:Gem::Version
152
152
  version: 0.5.8
153
153
  - !ruby/object:Gem::Dependency
@@ -184,6 +184,7 @@ email:
184
184
  - rich@reactor8.com
185
185
  executables:
186
186
  - dtk
187
+ - dtk-execute
187
188
  - dtk-shell
188
189
  extensions: []
189
190
  extra_rdoc_files: []
@@ -192,6 +193,7 @@ files:
192
193
  - Gemfile_dev
193
194
  - README.md
194
195
  - bin/dtk
196
+ - bin/dtk-execute
195
197
  - bin/dtk-shell
196
198
  - dtk-client.gemspec
197
199
  - lib/auxiliary.rb
@@ -269,6 +271,20 @@ files:
269
271
  - lib/dtk_constants.rb
270
272
  - lib/dtk_logger.rb
271
273
  - lib/error.rb
274
+ - lib/execute.rb
275
+ - lib/execute/command.rb
276
+ - lib/execute/command/api_call.rb
277
+ - lib/execute/command/api_call/map.rb
278
+ - lib/execute/command/api_call/service.rb
279
+ - lib/execute/command/api_call/translation_term.rb
280
+ - lib/execute/command/rest_call.rb
281
+ - lib/execute/command_processor.rb
282
+ - lib/execute/command_processor/rest_call.rb
283
+ - lib/execute/error_usage.rb
284
+ - lib/execute/examples.rb
285
+ - lib/execute/examples/add_tenant.rb
286
+ - lib/execute/execute_context.rb
287
+ - lib/execute/execute_context/result_store.rb
272
288
  - lib/git-logs/git.log
273
289
  - lib/parser/adapters/option_parser.rb
274
290
  - lib/parser/adapters/thor.rb
@@ -337,17 +353,17 @@ require_paths:
337
353
  - lib
338
354
  required_ruby_version: !ruby/object:Gem::Requirement
339
355
  requirements:
340
- - - ">="
356
+ - - ! '>='
341
357
  - !ruby/object:Gem::Version
342
358
  version: '0'
343
359
  required_rubygems_version: !ruby/object:Gem::Requirement
344
360
  requirements:
345
- - - ">="
361
+ - - ! '>='
346
362
  - !ruby/object:Gem::Version
347
363
  version: '0'
348
364
  requirements: []
349
365
  rubyforge_project:
350
- rubygems_version: 2.4.1
366
+ rubygems_version: 2.2.2
351
367
  signing_key:
352
368
  specification_version: 4
353
369
  summary: DTK CLI client for DTK server interaction.