dtk-client 0.7.1 → 0.7.1.1

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 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.