hmx_client 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,46 @@
1
+ require "hmx/command/base"
2
+ require 'date'
3
+
4
+ module HmxClient::Command
5
+
6
+ # Manipulate hmx fountains (auto id generators)
7
+ #
8
+ class Fountain < Base
9
+
10
+ # fountain
11
+ #
12
+ # Lists all of the fountains and their values
13
+ def index
14
+ fountainState = hmx.getFountainState([])
15
+ # fountainState is a map of fountainName => value
16
+ # Flip this into an array of "name" => name, "value" => value
17
+ objs = []
18
+ fountainState.each_pair do | key, value |
19
+ objs << { "name" => key, "value" => value }
20
+ end
21
+ cols = [ 'name', 'value' ]
22
+ headers = [ 'Fountain', 'Value' ]
23
+ display_table(objs, cols, headers)
24
+ end
25
+
26
+ # fountain:set
27
+ #
28
+ # Sets the new id for the fountain
29
+ #
30
+ def set
31
+ unless args.size > 1
32
+ raise CommandFailed, "Usage: hmx fountain:set <fountainId> <newValue>"
33
+ end
34
+ hmx.setFountainId(args)
35
+ end
36
+ # fountain:get
37
+ #
38
+ # Increments and returns a fountain value
39
+ def get
40
+ unless args.size > 0
41
+ raise CommandFailed, "Usage: hmx fountain:get <fountainId>"
42
+ end
43
+ display hmx.getFountain(args)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,20 @@
1
+ require "hmx/command/base"
2
+
3
+ module HmxClient::Command
4
+
5
+ # Get full document from hmx
6
+ #
7
+ class Get < Base
8
+
9
+ # get
10
+ #
11
+ # get a document from hmx, given its display name
12
+ #
13
+ def index
14
+ unless args.size > 0
15
+ raise CommandFailed, "Usage: hmx get displayname"
16
+ end
17
+ dout JSON.pretty_generate(hmx.getData(args))
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require "hmx/command/base"
2
+
3
+ module HmxClient::Command
4
+
5
+ # Get document content from hmx
6
+ #
7
+ class GetContent < Base
8
+
9
+ # getContent
10
+ #
11
+ # get the data part of a document from hmx, given its display name
12
+ #
13
+ def index
14
+ unless args.size > 0
15
+ raise CommandFailed, "Usage: hmx getContent displayname"
16
+ end
17
+ dout hmx.getContent(args)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,114 @@
1
+ require "hmx/command/base"
2
+
3
+ # list commands and display help
4
+ #
5
+ class HmxClient::Command::Help < HmxClient::Command::Base
6
+
7
+ PRIMARY_NAMESPACES = %w( config query get view)
8
+
9
+ # help [COMMAND]
10
+ #
11
+ # list available commands or display help for a specific command
12
+ #
13
+ def index
14
+ if command = args.shift
15
+ help_for_command(command)
16
+ else
17
+ help_for_root
18
+ end
19
+ end
20
+
21
+ alias_command "-h", "help"
22
+ alias_command "--help", "help"
23
+
24
+ def self.usage_for_command(command)
25
+ command = new.send(:commands)[command]
26
+ "Usage: hmx #{command[:banner]}" if command
27
+ end
28
+
29
+ private
30
+
31
+ def commands_for_namespace(name)
32
+ HmxClient::Command.commands.values.select do |command|
33
+ command[:namespace] == name && command[:command] != name
34
+ end
35
+ end
36
+
37
+ def namespaces
38
+ namespaces = HmxClient::Command.namespaces
39
+ namespaces
40
+ end
41
+
42
+ def commands
43
+ commands = HmxClient::Command.commands
44
+ HmxClient::Command.command_aliases.each do |new, old|
45
+ commands[new] = commands[old].dup
46
+ commands[new][:banner] = "#{new} #{commands[new][:banner].split(" ", 2)[1]}"
47
+ commands[new][:command] = new
48
+ commands[new][:namespace] = nil
49
+ end
50
+ commands
51
+ end
52
+
53
+ def primary_namespaces
54
+ PRIMARY_NAMESPACES.map { |name| namespaces[name] }.compact
55
+ end
56
+
57
+ def additional_namespaces
58
+ (namespaces.values - primary_namespaces).sort_by { |n| n[:name] }
59
+ end
60
+
61
+ def summary_for_namespaces(namespaces)
62
+ size = longest(namespaces.map { |n| n[:name] })
63
+ namespaces.each do |namespace|
64
+ name = namespace[:name]
65
+ namespace[:description] ||= legacy_help_for_namespace(name)
66
+ puts " %-#{size}s # %s" % [ name, namespace[:description] ]
67
+ end
68
+ end
69
+
70
+ def help_for_root
71
+ puts "Usage: hmx COMMAND [command-specific-options]"
72
+ puts
73
+ puts "Primary help topics, type \"hmx help TOPIC\" for more details:"
74
+ puts
75
+ summary_for_namespaces(primary_namespaces)
76
+ puts
77
+ puts "Additional topics:"
78
+ puts
79
+ summary_for_namespaces(additional_namespaces)
80
+ puts
81
+ end
82
+
83
+ def help_for_namespace(name)
84
+ namespace_commands = commands_for_namespace(name)
85
+
86
+ unless namespace_commands.empty?
87
+ size = longest(namespace_commands.map { |c| c[:banner] })
88
+ namespace_commands.sort_by { |c| c[:banner].to_s }.each do |command|
89
+ next if command[:help] =~ /DEPRECATED/
90
+ command[:summary] ||= legacy_help_for_command(command[:command])
91
+ puts " %-#{size}s # %s" % [ command[:banner], command[:summary] ]
92
+ end
93
+ end
94
+ end
95
+
96
+ def help_for_command(name)
97
+ command = commands[name]
98
+
99
+ if command
100
+ if command[:help].strip.length > 0
101
+ puts "Usage: hmx #{command[:banner]}"
102
+ puts command[:help].split("\n")[1..-1].join("\n")
103
+ puts
104
+ end
105
+ end
106
+
107
+ unless commands_for_namespace(name).empty?
108
+ puts "Additional commands, type \"hmx help COMMAND\" for more details:"
109
+ puts
110
+ help_for_namespace(name)
111
+ puts
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,22 @@
1
+ require "hmx/command/base"
2
+
3
+ module HmxClient::Command
4
+
5
+ # Perform queries against data in hmx
6
+ #
7
+ class Query < Base
8
+
9
+ # query
10
+ #
11
+ # query for documents in a type
12
+ #
13
+ # TYPENAME
14
+ #
15
+ def index
16
+ unless args.size > 0
17
+ raise CommandFailed, "Usage: hmx query <typeName> [<key>=<value>, [<key2>=<value2>...]]"
18
+ end
19
+ display hmx.query(args.shift, nil)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,35 @@
1
+ require "hmx/command/base"
2
+ require 'date'
3
+
4
+ module HmxClient::Command
5
+
6
+ # Display and manage session information for hmx
7
+ #
8
+ class Session < Base
9
+
10
+ # session
11
+ #
12
+ # List the sessions and their status on hmx
13
+ def index
14
+ displayNames = hmx.query('sys.session', nil)
15
+ objs = []
16
+ displayNames.each do | name |
17
+ data = hmx.getContent([name])
18
+ dval = JSON.parse(data)
19
+ dval["MXSession"]["validUntil"] = Time.at(dval["MXSession"]["validUntil"] / 1000).to_datetime.strftime
20
+ objs << dval["MXSession"]
21
+ end
22
+ cols = [ 'sessionId', 'userId', 'authenticated','validUntil' ]
23
+ headers = [ 'Session', 'Username', 'Authenticated', 'ValidUntil' ]
24
+ display_table(objs, cols, headers)
25
+ end
26
+
27
+ # session:expire
28
+ #
29
+ # Forces the expiry of any old sessions
30
+ #
31
+ def expire
32
+ display hmx.expireSessions([])
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,32 @@
1
+ require "hmx/command/base"
2
+ require 'date'
3
+
4
+ module HmxClient::Command
5
+
6
+ # Display and manage tasks in hmx
7
+ #
8
+ class Task < Base
9
+
10
+ # task
11
+ #
12
+ # List all of the tasks
13
+ def index
14
+ tasks = hmx.getAllTasks([])
15
+ objs = []
16
+ tasks.each do | t |
17
+ task = hmx.getTask([t])
18
+ objs << task
19
+ end
20
+ headers = [ "TaskId", "TaskType", "TaskState", "GroupId" ]
21
+ cols = [ "taskId", "taskType", "taskState", "group" ]
22
+ display_table(objs, cols, headers)
23
+ end
24
+ # task:purge
25
+ #
26
+ # Purge completed tasks
27
+ def purge
28
+ hmx.purgeTasks([])
29
+ display "Purge complete"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ require "hmx/command/base"
2
+ require 'date'
3
+
4
+ module HmxClient::Command
5
+
6
+ # Display and manage type information in hmx
7
+ #
8
+ class Type < Base
9
+
10
+ # type
11
+ #
12
+ # Display information about a HMX type
13
+ def index
14
+ puts JSON.pretty_generate(hmx.getType(args.shift))
15
+ end
16
+
17
+ # type:create
18
+ #
19
+ # Create a type with default settings - no triggers, no entitlements
20
+ def create
21
+ typeInfo = { "name" => args.shift, "triggers" => [], "typeNature" => "CONTENT", "typeIndexScript" => "", "typeAspect" => "JSONDOCUMENT" }
22
+ hmx.updateType(typeInfo)
23
+ puts "Done..."
24
+ end
25
+
26
+ # type:clone-ent
27
+ #
28
+ # Clone the entitlements from one type to another
29
+ #
30
+ # <srcType> <targType>
31
+ def clone
32
+ # We basically load the documents for sys.ent/type/[source]/query and sys.ent/type/[source]/query and copy them to the target
33
+ sourceType = args.shift
34
+ targetType = args.shift
35
+ arr = JSON.parse(hmx.getContent(["sys.ent/type/#{ sourceType }/get"]))
36
+ arr["MXEntitlement"]["entitlementPath"] = "type/#{ targetType }/get"
37
+ hmx.putSimpleData([ "sys.ent/type/#{ targetType}/get", JSON.generate(arr)])
38
+
39
+ arr = JSON.parse(hmx.getContent(["sys.ent/type/#{ sourceType }/query"]))
40
+ arr["MXEntitlement"]["entitlementPath"] = "type/#{ targetType }/query"
41
+ hmx.putSimpleData([ "sys.ent/type/#{ targetType}/query", JSON.generate(arr)])
42
+ puts "Done..."
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,68 @@
1
+ require "hmx/command/base"
2
+
3
+ module HmxClient::Command
4
+
5
+ # Manipulate user entities in hmx
6
+ #
7
+ class User < Base
8
+
9
+ # user
10
+ #
11
+ # manipulate user enties in hMX
12
+ #
13
+ #
14
+ def index
15
+ unless args.size > 0
16
+ raise CommandFailed, "Usage: hmx user <userId>"
17
+ end
18
+ userName = args.shift
19
+ dout JSON.pretty_generate(hmx.getData(["sys.user/#{userName}"]))
20
+ end
21
+
22
+ # user:list
23
+ #
24
+ # Lists all of the users in the system
25
+
26
+ def list
27
+ views = hmx.query("sys.user", nil)
28
+ views.each { | v |
29
+ display v.rpartition('/')[2]
30
+ }
31
+ end
32
+
33
+ # user:get
34
+ #
35
+ # Retrieves the definition of a user
36
+ #
37
+ def get
38
+ index
39
+ end
40
+
41
+ # user:password
42
+ #
43
+ # Sets the password for a user
44
+ #
45
+ def password
46
+ unless args.size > 1
47
+ raise CommandFailed, "Usage: hmx user:password <userId> <newPassword>"
48
+ end
49
+ user = args.shift
50
+ userName = "sys.user/#{user}"
51
+ password = Digest::MD5.hexdigest(args.shift)
52
+ dataDocument = hmx.getData([userName])
53
+ dataDocument['document']['MXUser']['hashPassword'] = password
54
+ display hmx.putData([JSON.generate(dataDocument)])
55
+ end
56
+
57
+ # user:delete
58
+ #
59
+ # Removes a user
60
+ #
61
+ def delete
62
+ # We also need to remove the user reference from any groups they belong to (sys.entgroup)
63
+ # We should be clever and use a custom view for that purpose
64
+ # something like
65
+ # (fn[param] (fn[x] (contains (param "user" (.get x '(:document :MXEntitlementGroup :users ))))))
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,155 @@
1
+ require "hmx/command/base"
2
+
3
+ module HmxClient::Command
4
+
5
+ # Display the results of a view and list all views
6
+ #
7
+ class View < Base
8
+
9
+ # view
10
+ #
11
+ # run a view in hmx, passing in a view name and an input to the filter function
12
+ #
13
+ #
14
+ def index
15
+ unless args.size > 0
16
+ raise CommandFailed, "Usage: hmx view <viewName> <filterContext>"
17
+ end
18
+ viewData = hmx.runView(args.shift, JSON.parse(args.shift))
19
+ resp = ''
20
+ viewData.each { | line |
21
+ line.each { | cell | resp = resp + "%20.20s\t" % cell }
22
+ resp = resp + "\n"
23
+ }
24
+ dout resp
25
+ end
26
+
27
+ # view:list
28
+ #
29
+ # Lists all of the views in the system
30
+
31
+ def list
32
+ views = hmx.query("sys.view", nil)
33
+ views.each { | v |
34
+ display v.rpartition('/')[2]
35
+ }
36
+ end
37
+
38
+ # view:get
39
+ #
40
+ # Retrieves the definition of a view
41
+ #
42
+ def get
43
+ unless args.size > 0
44
+ raise CommandFailed, "Usage: hmx view:get <viewName>"
45
+ end
46
+ typeName = "sys.view/#{args.shift}"
47
+ display "Retrieving #{ typeName }"
48
+ dout JSON.pretty_generate(hmx.getData([typeName]))
49
+ end
50
+
51
+ # view:create
52
+ #
53
+ # Create a new (initially blank) view.
54
+ # You will then need to call update to set the filter function, map function, query params and
55
+ # result columns.
56
+ #
57
+ # Views are based on types, for create define a name and the type
58
+ def create
59
+ unless args.size > 1
60
+ raise CommanFailed, "Usage: hmx view:create <viewName> <typeName>"
61
+ end
62
+ view = args.shift
63
+ viewName = "sys.view/#{view}"
64
+ typeName = args.shift
65
+
66
+ dataDocument = {
67
+ "MXView" => {
68
+ :typeName => typeName,
69
+ :parameterNames => [],
70
+ :filterFn => "",
71
+ :mappingFn => "",
72
+ :resultColumns => [],
73
+ :viewName => view
74
+ }
75
+ }
76
+
77
+ dout JSON.pretty_generate(hmx.putSimpleData([viewName, JSON.generate(dataDocument)]))
78
+ end
79
+
80
+ # view:updateFilter
81
+ #
82
+ # Set the filter function for a view
83
+ #
84
+ def updateFilter
85
+ unless args.size > 1
86
+ raise CommandFailed, "Usage: hmx view:updateFilter <viewName> <filterFn>"
87
+ end
88
+ view = args.shift
89
+ viewName = "sys.view/#{view}"
90
+ filterFn = args.shift
91
+
92
+ dataDocument = hmx.getData([viewName])
93
+ puts dataDocument
94
+ dataDocument['document']['MXView']['filterFn'] = filterFn
95
+ display hmx.putData([JSON.generate(dataDocument)])
96
+ end
97
+ # view:updateMap
98
+ #
99
+ # Set the map function for a view
100
+ #
101
+ def updateMap
102
+ unless args.size > 1
103
+ raise CommandFailed, "Usage: hmx view:updateMap <viewName> <filterFn>"
104
+ end
105
+ view = args.shift
106
+ viewName = "sys.view/#{view}"
107
+ mapFn = args.shift
108
+ dataDocument = hmx.getData([viewName])
109
+ dataDocument['document']['MXView']['mappingFn'] = mapFn
110
+ display hmx.putData([JSON.generate(dataDocument)])
111
+ end
112
+ # view:updateParam
113
+ #
114
+ # Set the parameter names for a view
115
+ #
116
+ def updateParam
117
+ unless args.size > 1
118
+ raise CommandFailed, "Usage: hmx view:updateParam <viewName> <param> [<param2> ...]"
119
+ end
120
+ view = args.shift
121
+ viewName = "sys.view/#{view}"
122
+ dataDocument = hmx.getData([viewName])
123
+ dataDocument['document']['MXView']['parameterNames'] = args
124
+ display hmx.putData([JSON.generate(dataDocument)])
125
+ end
126
+ # view:updateResult
127
+ #
128
+ # Set the result names for a view
129
+ #
130
+ def updateResult
131
+ unless args.size > 1
132
+ raise CommandFailed, "Usage: hmx view:updateResult <viewName> <param> [<param2> ...]"
133
+ end
134
+ view = args.shift
135
+ viewName = "sys.view/#{view}"
136
+
137
+ dataDocument = hmx.getData([viewName])
138
+ dataDocument['document']['MXView']['resultColumns'] = args
139
+ display hmx.putData([JSON.generate(dataDocument)])
140
+ end
141
+ # view:delete
142
+ #
143
+ # Delete a view definition
144
+ #
145
+ def delete
146
+ unless args.size >0
147
+ raise CommandFailed, "Usage: hmx view:delete <viewName>"
148
+ end
149
+ view = args.shift
150
+ viewName = "sys.view/#{view}"
151
+ display hmx.deleteData(viewName)
152
+ end
153
+
154
+ end
155
+ end
@@ -0,0 +1,140 @@
1
+ require "optparse"
2
+ require "hmx/helpers"
3
+
4
+ module HmxClient
5
+ module Command
6
+ class InvalidCommand < RuntimeError; end
7
+ class CommandFailed < RuntimeError; end
8
+
9
+ extend HmxClient::Helpers
10
+
11
+ def self.load
12
+ Dir[File.join(File.dirname(__FILE__), "command", "*.rb")].each do | file |
13
+ require file
14
+ end
15
+ end
16
+
17
+ def self.commands
18
+ @@command ||= {}
19
+ end
20
+
21
+ def self.command_aliases
22
+ @@command_aliases ||= {}
23
+ end
24
+
25
+ def self.namespaces
26
+ @@namespaces ||= {}
27
+ end
28
+
29
+ def self.register_command(command)
30
+ commands[command[:command]] = command
31
+ end
32
+
33
+ def self.register_namespace(namespace)
34
+ namespaces[namespace[:name]] = namespace
35
+ end
36
+
37
+ def self.current_command
38
+ @current_command
39
+ end
40
+
41
+ def self.current_args
42
+ @current_args
43
+ end
44
+
45
+ def self.current_options
46
+ @current_options
47
+ end
48
+
49
+ def self.global_options
50
+ @global_options ||= []
51
+ end
52
+
53
+ def self.global_option(name, *args)
54
+ global_options << { :name => name, :args => args }
55
+ end
56
+
57
+ global_option :debug, "--debug", "-d"
58
+ global_option :fileIn, "--file-in FILE", "-i"
59
+ global_option :fileOut, "--file-out FILE", "-o"
60
+
61
+ def self.prepare_run(cmd, args=[])
62
+ command = parse(cmd)
63
+
64
+ unless command
65
+ error " ! #{cmd} is not a hmx command. See 'hmx help'."
66
+ return
67
+ end
68
+
69
+ @current_command = cmd
70
+ opts = {}
71
+ invalid_options = []
72
+
73
+ parser = OptionParser.new do | parser |
74
+ global_options.each do | global_option |
75
+ parser.on(*global_option[:args]) do | value |
76
+ opts[global_option[:name]] = value
77
+ end
78
+ end
79
+ command[:options].each do | name, option |
80
+ parser.on("-#{option[:short]}", "--#{option[:long]}", option[:desc]) do | value |
81
+ opts[name.gsub("-","_").to_sym] = value
82
+ end
83
+ end
84
+ end
85
+
86
+ begin
87
+ parser.order!(args) do |nonopt|
88
+ invalid_options << nonopt
89
+ end
90
+ rescue OptionParser::InvalidOption => ex
91
+ invalid_options << ex.args.first
92
+ retry
93
+ end
94
+
95
+ raise OptionParser::ParseError if opts[:help]
96
+
97
+ args.concat(invalid_options)
98
+
99
+ @current_args = args
100
+ @current_options = opts
101
+
102
+ [ command[:klass].new(args.dup, opts.dup), command[:method] ]
103
+ end
104
+
105
+ def self.debug?
106
+ @current_options.has_key?(:debug)
107
+ end
108
+
109
+ def self.fileIn
110
+ @current_options[:fileIn]
111
+ end
112
+
113
+ def self.fileOut
114
+ @current_options[:fileOut]
115
+ end
116
+
117
+ def self.run(cmd, arguments=[])
118
+ object, method = prepare_run(cmd, arguments.dup)
119
+ object.send(method)
120
+ rescue InvalidCommand
121
+ error "Unknown command. Run 'hmx help' for usage information."
122
+ rescue CommandFailed => e
123
+ error e.message
124
+ rescue OptionParser::ParseError => ex
125
+ commands[cmd] ? run("help", [cmd]) : run("help")
126
+ rescue Interrupt => e
127
+ error "\n[cancelled]"
128
+ end
129
+
130
+ def self.parse(cmd)
131
+ commands[cmd] || commands[command_aliases[cmd]]
132
+ end
133
+
134
+ def self.extract_error(body, options={})
135
+ default_error = block_given ? yield : "Internal server error"
136
+ end
137
+ end
138
+ end
139
+
140
+