MuranoCLI 2.2.4 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/.agignore +3 -0
  3. data/.gitignore +18 -1
  4. data/.rubocop.yml +222 -0
  5. data/.trustme.sh +185 -0
  6. data/.trustme.vim +24 -0
  7. data/Gemfile +23 -4
  8. data/LICENSE.txt +1 -1
  9. data/MuranoCLI.gemspec +43 -8
  10. data/README.markdown +9 -11
  11. data/Rakefile +187 -143
  12. data/TODO.taskpaper +2 -2
  13. data/bin/murano +51 -52
  14. data/docs/basic_example.rst +436 -0
  15. data/docs/completions/murano_completion-bash +3484 -0
  16. data/docs/demo.md +32 -32
  17. data/docs/develop.rst +391 -0
  18. data/lib/MrMurano.rb +21 -7
  19. data/lib/MrMurano/Account.rb +159 -174
  20. data/lib/MrMurano/Business.rb +381 -0
  21. data/lib/MrMurano/Config-Migrate.rb +32 -26
  22. data/lib/MrMurano/Config.rb +407 -128
  23. data/lib/MrMurano/Content.rb +191 -0
  24. data/lib/MrMurano/Gateway.rb +489 -0
  25. data/lib/MrMurano/Keystore.rb +48 -0
  26. data/lib/MrMurano/Passwords.rb +103 -0
  27. data/lib/MrMurano/ProjectFile.rb +121 -79
  28. data/lib/MrMurano/ReCommander.rb +114 -10
  29. data/lib/MrMurano/Setting.rb +90 -0
  30. data/lib/MrMurano/Solution-ServiceConfig.rb +89 -45
  31. data/lib/MrMurano/Solution-Services.rb +461 -166
  32. data/lib/MrMurano/Solution-Users.rb +70 -31
  33. data/lib/MrMurano/Solution.rb +372 -13
  34. data/lib/MrMurano/SolutionId.rb +73 -0
  35. data/lib/MrMurano/SyncRoot.rb +137 -0
  36. data/lib/MrMurano/SyncUpDown.rb +594 -284
  37. data/lib/MrMurano/Webservice-Cors.rb +71 -0
  38. data/lib/MrMurano/Webservice-Endpoint.rb +234 -0
  39. data/lib/MrMurano/Webservice-File.rb +193 -0
  40. data/lib/MrMurano/Webservice.rb +51 -0
  41. data/lib/MrMurano/commands.rb +18 -15
  42. data/lib/MrMurano/commands/business.rb +300 -6
  43. data/lib/MrMurano/commands/completion-bash.erb +166 -0
  44. data/lib/MrMurano/commands/{zshcomplete.erb → completion-zsh.erb} +0 -0
  45. data/lib/MrMurano/commands/completion.rb +76 -39
  46. data/lib/MrMurano/commands/config.rb +108 -44
  47. data/lib/MrMurano/commands/content.rb +115 -72
  48. data/lib/MrMurano/commands/cors.rb +29 -14
  49. data/lib/MrMurano/commands/devices.rb +286 -0
  50. data/lib/MrMurano/commands/domain.rb +52 -12
  51. data/lib/MrMurano/commands/gb.rb +24 -9
  52. data/lib/MrMurano/commands/globals.rb +64 -0
  53. data/lib/MrMurano/commands/init.rb +377 -155
  54. data/lib/MrMurano/commands/keystore.rb +92 -82
  55. data/lib/MrMurano/commands/link.rb +300 -0
  56. data/lib/MrMurano/commands/login.rb +74 -11
  57. data/lib/MrMurano/commands/logs.rb +63 -32
  58. data/lib/MrMurano/commands/mock.rb +57 -29
  59. data/lib/MrMurano/commands/password.rb +57 -39
  60. data/lib/MrMurano/commands/postgresql.rb +127 -94
  61. data/lib/MrMurano/commands/settings.rb +203 -0
  62. data/lib/MrMurano/commands/show.rb +79 -38
  63. data/lib/MrMurano/commands/solution.rb +423 -5
  64. data/lib/MrMurano/commands/solution_picker.rb +547 -0
  65. data/lib/MrMurano/commands/status.rb +195 -61
  66. data/lib/MrMurano/commands/sync.rb +78 -39
  67. data/lib/MrMurano/commands/timeseries.rb +71 -55
  68. data/lib/MrMurano/commands/tsdb.rb +113 -87
  69. data/lib/MrMurano/commands/usage.rb +57 -15
  70. data/lib/MrMurano/hash.rb +100 -10
  71. data/lib/MrMurano/http.rb +187 -43
  72. data/lib/MrMurano/makePretty.rb +16 -14
  73. data/lib/MrMurano/optparse.rb +2178 -0
  74. data/lib/MrMurano/progress.rb +138 -0
  75. data/lib/MrMurano/schema/resource-v1.0.0.yaml +32 -0
  76. data/lib/MrMurano/template/projectFile.murano.erb +16 -13
  77. data/lib/MrMurano/verbosing.rb +166 -29
  78. data/lib/MrMurano/version.rb +30 -1
  79. data/spec/Account-Passwords_spec.rb +21 -4
  80. data/spec/Account_spec.rb +69 -146
  81. data/spec/Business_spec.rb +290 -0
  82. data/spec/ConfigFile_spec.rb +1 -0
  83. data/spec/ConfigMigrate_spec.rb +12 -8
  84. data/spec/Config_spec.rb +40 -34
  85. data/spec/Content_spec.rb +363 -0
  86. data/spec/GatewayBase_spec.rb +54 -0
  87. data/spec/GatewayDevice_spec.rb +321 -0
  88. data/spec/GatewayResource_spec.rb +266 -0
  89. data/spec/GatewaySettings_spec.rb +120 -0
  90. data/spec/Http_spec.rb +18 -8
  91. data/spec/Mock_spec.rb +2 -2
  92. data/spec/ProjectFile_spec.rb +25 -14
  93. data/spec/Setting_spec.rb +110 -0
  94. data/spec/Solution-ServiceConfig_spec.rb +44 -5
  95. data/spec/Solution-ServiceEventHandler_spec.rb +23 -14
  96. data/spec/Solution-ServiceModules_spec.rb +47 -37
  97. data/spec/Solution-UsersRoles_spec.rb +10 -8
  98. data/spec/Solution_spec.rb +17 -8
  99. data/spec/SyncRoot_spec.rb +46 -20
  100. data/spec/SyncUpDown_spec.rb +437 -201
  101. data/spec/Verbosing_spec.rb +12 -4
  102. data/spec/{Solution-Cors_spec.rb → Webservice-Cors_spec.rb} +23 -20
  103. data/spec/{Solution-Endpoint_spec.rb → Webservice-Endpoint_spec.rb} +43 -41
  104. data/spec/{Solution-File_spec.rb → Webservice-File_spec.rb} +44 -33
  105. data/spec/Webservice-Setting_spec.rb +89 -0
  106. data/spec/_workspace.rb +4 -4
  107. data/spec/cmd_business_spec.rb +9 -4
  108. data/spec/cmd_common.rb +44 -1
  109. data/spec/cmd_content_spec.rb +43 -17
  110. data/spec/cmd_cors_spec.rb +4 -4
  111. data/spec/cmd_device_spec.rb +61 -16
  112. data/spec/cmd_domain_spec.rb +29 -6
  113. data/spec/cmd_init_spec.rb +281 -126
  114. data/spec/cmd_keystore_spec.rb +3 -3
  115. data/spec/cmd_link_spec.rb +98 -0
  116. data/spec/cmd_password_spec.rb +1 -1
  117. data/spec/cmd_setting_application_spec.rb +260 -0
  118. data/spec/cmd_setting_product_spec.rb +220 -0
  119. data/spec/cmd_status_spec.rb +223 -114
  120. data/spec/cmd_syncdown_spec.rb +115 -35
  121. data/spec/cmd_syncup_spec.rb +68 -15
  122. data/spec/cmd_usage_spec.rb +35 -8
  123. data/spec/fixtures/dumped_config +6 -4
  124. data/spec/fixtures/gateway_resource_files/resources.notyaml +12 -0
  125. data/spec/fixtures/gateway_resource_files/resources.yaml +13 -0
  126. data/spec/fixtures/gateway_resource_files/resources_invalid.yaml +13 -0
  127. data/spec/fixtures/mrmuranorc_deleted_bob +0 -2
  128. data/spec/fixtures/product_spec_files/lightbulb.yaml +20 -13
  129. data/spec/fixtures/{syncable_content → syncable_conflict}/services/devdata.lua +1 -1
  130. data/spec/fixtures/{syncable_content → syncable_conflict}/services/timers.lua +0 -0
  131. data/spec/spec_helper.rb +5 -0
  132. metadata +262 -171
  133. data/bin/mr +0 -8
  134. data/lib/MrMurano/Product-1P-Device.rb +0 -145
  135. data/lib/MrMurano/Product-Resources.rb +0 -205
  136. data/lib/MrMurano/Product.rb +0 -358
  137. data/lib/MrMurano/Solution-Cors.rb +0 -47
  138. data/lib/MrMurano/Solution-Endpoint.rb +0 -191
  139. data/lib/MrMurano/Solution-File.rb +0 -166
  140. data/lib/MrMurano/commands/assign.rb +0 -57
  141. data/lib/MrMurano/commands/businessList.rb +0 -45
  142. data/lib/MrMurano/commands/product.rb +0 -14
  143. data/lib/MrMurano/commands/productCreate.rb +0 -39
  144. data/lib/MrMurano/commands/productDelete.rb +0 -33
  145. data/lib/MrMurano/commands/productDevice.rb +0 -87
  146. data/lib/MrMurano/commands/productDeviceIdCmds.rb +0 -89
  147. data/lib/MrMurano/commands/productList.rb +0 -45
  148. data/lib/MrMurano/commands/productWrite.rb +0 -27
  149. data/lib/MrMurano/commands/solutionCreate.rb +0 -41
  150. data/lib/MrMurano/commands/solutionDelete.rb +0 -34
  151. data/lib/MrMurano/commands/solutionList.rb +0 -45
  152. data/spec/ProductBase_spec.rb +0 -113
  153. data/spec/ProductContent_spec.rb +0 -162
  154. data/spec/ProductResources_spec.rb +0 -329
  155. data/spec/Product_1P_Device_spec.rb +0 -202
  156. data/spec/Product_1P_RPC_spec.rb +0 -175
  157. data/spec/Product_spec.rb +0 -153
  158. data/spec/Solution-ServiceDevice_spec.rb +0 -176
  159. data/spec/cmd_assign_spec.rb +0 -51
@@ -10,8 +10,8 @@ Commands:
10
10
  - Empty sub-commands should return help. @done(2016-11-21)
11
11
  There are a bunch of empty sub-commands that prefix another layer. Such as
12
12
  assign, content, product, and others. Those should be impemented as a ‘help’
13
- only command. That is they should return help like the plain `mr` command, but
14
- just for their sub-section of things
13
+ only command. That is they should return help like the plain `murano` command,
14
+ but just for their sub-section of things
15
15
  - Errors and Warnings should get sent to STDERR @done(2016-11-03)
16
16
  - Need a more consistent output format. 'pp' is still used in many places. @done(2016-11-03)
17
17
  Maybe have a tool setting for output format? json, yaml, pp, csv, table ?
data/bin/murano CHANGED
@@ -1,71 +1,61 @@
1
1
  #!/usr/bin/env ruby
2
+ # Last Modified: 2017.08.16 /coding: utf-8
3
+ # frozen_string_literal: true
4
+
5
+ # Copyright © 2016-2017 Exosite LLC.
6
+ # License: MIT. See LICENSE.txt.
7
+ # vim:tw=0:ts=2:sw=2:et:ai
2
8
 
3
- require 'rubygems'
4
9
  require 'commander/import'
10
+ require 'dotenv'
11
+ require 'highline'
5
12
  require 'pathname'
13
+ #require 'pp'
14
+ require 'rainbow'
15
+ require 'rubygems'
6
16
  require 'MrMurano'
7
- require 'pp'
8
- require 'dotenv'
17
+ require 'MrMurano/Config'
18
+ require 'MrMurano/ProjectFile'
19
+
20
+ # DEVs: Store environs in an .env file that gets loaded here. Alternatively,
21
+ # run a Bash or similar script before you start developing.
9
22
  Dotenv.load
10
23
 
11
- Signal.trap('INT', 'EXIT') # Don't drop traces on ^C
24
+ # Don't drop traces on ^C.
25
+ # EXPLAIN/2017-06-30: [lb] not sure what "drop traces" means.
26
+ # What happens if we don't trap Ctrl-C?
27
+ # NOTE: The second parameter is either a string, or a command or block to
28
+ # call or run. Ruby honors certain special strings, like 'EXIT':
29
+ # "If the command is “EXIT”, the script will be terminated by the signal."
30
+ # Per https://ruby-doc.org/core-2.2.0/Signal.html
31
+ Signal.trap('INT', 'EXIT')
12
32
 
13
33
  program :version, MrMurano::VERSION
14
- program :description, %{Manage a Solution and Product in Exosite's Murano}
15
34
 
16
- global_option('-V', '--verbose', 'Be chatty') {
17
- $cfg['tool.verbose'] = true
18
- }
19
- global_option('-n', '--dry', %{Don't run actions that make changes}) {
20
- $cfg['tool.dry'] = true
21
- $cfg['tool.verbose'] = true # dry implies verbose
22
- }
23
- global_option('-L', '--curl', 'Print out a curl command for each network call') {
24
- $cfg['tool.curldebug'] = true
25
- }
26
- global_option '--skip-plugins', %{Don't load plugins. Good for when one goes bad.}
35
+ program :description, %(
36
+ Manage Applications and Products in Exosite's Murano
37
+ ).strip
27
38
 
28
- global_option('-C', '--configfile FILE', %{Load additional configuration file}) {|file|
29
- # this is called after all of the top level code in this file.
30
- $cfg.load_specific(file)
31
- }
32
- global_option('-c', '--config KEY=VALUE', %{Set a single config key}) {|param|
33
- key, value = param.split('=', 2)
34
- # a=b :> ["a","b"]
35
- # a= :> ["a",""]
36
- # a :> ["a"]
37
- raise "Bad config '#{param}'" if key.nil?
38
- if value.nil? then
39
- $cfg[key] = 'true'
40
- else
41
- $cfg[key] = value
42
- end
43
- }
39
+ # The Commander defaults to paged help.
40
+ # The user can disable with --no-page, e.g.,
41
+ # alias murano='murano --no-page'
42
+ if ARGV.include?('--no-page')
43
+ program :help_paging, false
44
+ ARGV.delete('--no-page')
45
+ end
44
46
 
45
47
  default_command :help
46
- #default_command :syncup
47
48
 
48
- $cfg = MrMurano::Config.new
49
- $cfg.load
50
- $project = MrMurano::ProjectFile.new
51
- $project.load
52
-
53
- # Basic command support is:
54
- # - read/write config file in [Project, User, System] (all are optional)
55
- # - TODO: Introspection for tab completion.
56
- # - TODO: Look for tools in PATH that are +x and "mr-foo..."
57
-
58
-
59
- # Look for plug-ins
49
+ # Look for plug-ins.
60
50
  pgds = [
61
51
  Pathname.new(Dir.home) + '.mrmurano' + 'plugins',
62
- Pathname.new(Dir.home) + '.murano' + 'plugins'
52
+ Pathname.new(Dir.home) + '.murano' + 'plugins',
63
53
  ]
64
54
  # Add plugin dirs from configs
65
55
  # This is run before the command line options are parsed, so need to check old way.
66
- if not ARGV.include? '--skip-plugins' then
67
- pgds << Pathname.new(ENV['MR_MURANO_PLUGIN_DIR']) if ENV.has_key? 'MR_MURANO_PLUGIN_DIR'
68
- pgds << Pathname.new(ENV['MURANO_PLUGIN_DIR']) if ENV.has_key? 'MURANO_PLUGIN_DIR'
56
+ unless ARGV.include? '--skip-plugins'
57
+ pgds << Pathname.new(ENV['MR_MURANO_PLUGIN_DIR']) if ENV.key? 'MR_MURANO_PLUGIN_DIR'
58
+ pgds << Pathname.new(ENV['MURANO_PLUGIN_DIR']) if ENV.key? 'MURANO_PLUGIN_DIR'
69
59
  pgds.each do |path|
70
60
  next unless path.exist?
71
61
  path.each_child do |plugin|
@@ -74,11 +64,20 @@ if not ARGV.include? '--skip-plugins' then
74
64
  next if plugin.basename.fnmatch('.*') # don't read anything starting with .
75
65
  begin
76
66
  require plugin.to_s
77
- rescue Exception => e
78
- $stderr.puts "Failed to load plugin at #{plugin} because #{e}"
67
+ #rescue Exception => err
68
+ rescue StandardError => err
69
+ $stderr.puts "Failed to load plugin at #{plugin} because #{err}"
79
70
  end
80
71
  end
81
72
  end
82
73
  end
83
74
 
84
- # vim: set ai et sw=2 ts=2 :
75
+ # Look for .murano/config files.
76
+ $cfg = MrMurano::Config.new(::Commander::Runner.instance)
77
+ $cfg.load
78
+ $cfg.validate_cmd
79
+
80
+ # Look for a (legacy) Solutionfile.json.
81
+ $project = MrMurano::ProjectFile.new
82
+ $project.load
83
+
@@ -0,0 +1,436 @@
1
+ #######################
2
+ Basic MuranoCLI Example
3
+ #######################
4
+
5
+ Learn Murano the Easy Way
6
+ =========================
7
+
8
+ This document illustrates how to setup a very basic Murano project.
9
+
10
+ It shows how to use the Murano CLI tool (also called "MuranoCLI", or
11
+ just "MurCLI") to create an Application and Product, and how to send
12
+ data to the Product that gets processed by the Application.
13
+
14
+ Prerequisites
15
+ =============
16
+
17
+ It is assumed that you have already created a Murano business account,
18
+ and that you have installed MurCLI on your local machine.
19
+
20
+ - To sign up for a free Murano business account, visit:
21
+
22
+ https://exosite.com/signup/
23
+
24
+ - To install MurCLI, run:
25
+
26
+ ``gem install MuranoCLI``
27
+
28
+ If you need installation help, look at the `README
29
+ <https://github.com/exosite/MuranoCLI#install>`__.
30
+
31
+ Start Fresh
32
+ ===========
33
+
34
+ You can skip this section if you've never setup a business before.
35
+
36
+ But if you've already created a business, and if you've already
37
+ created an Application and/or Product for it, you can clean up
38
+ that business so we can start over.
39
+
40
+ First, list your businesses and find the one you want to reset. E.g.,
41
+
42
+ .. code-block:: text
43
+
44
+ $ murano business list
45
+
46
+ +------------------+-------+-------------------+
47
+ | bizid | role | name |
48
+ +------------------+-------+-------------------+
49
+ | 4o54fc55olth85mi | owner | My First Business |
50
+ | fu5rse4xdww2ke29 | admin | Collaborative Biz |
51
+ | ct7rmoz3hu34ygb9 | owner | Another of My Biz |
52
+ +------------------+-------+-------------------+
53
+
54
+ NOTE: If you have never used MurCLI before, or if you've logged out
55
+ of Murano, MurCLI will tell you to logon first. E.g.,
56
+
57
+ .. code-block:: text
58
+
59
+ $ murano business list
60
+
61
+ No Murano user account found.
62
+ Please login using `murano login` or `murano init`.
63
+ Or set your password with `murano password set <username>`.
64
+
65
+ Next, remove all solutions (Applications and Products) from that project.
66
+
67
+ .. code-block:: text
68
+
69
+ $ murano solutions expunge -y -c business.id=ct7rmoz3hu34ygb9
70
+
71
+ Deleted 2 solutions
72
+
73
+ Logout of Murano. This removes your username and password so
74
+ that MurCLI will ask you to reenter your username and password.
75
+
76
+ .. code-block:: text
77
+
78
+ $ murano logout
79
+
80
+ You might also have environment variables set. Clear those for
81
+ the sake of this walk-through.
82
+
83
+ .. code-block:: text
84
+
85
+ $ export MURANO_CONFIGFILE=
86
+ $ export MURANO_PASSWORD=
87
+
88
+ Create a New Project
89
+ ====================
90
+
91
+ Create a new directory for your project.
92
+
93
+ .. code-block:: text
94
+
95
+ $ mkdir ~/murano/projects/basic_test
96
+
97
+ $ cd ~/murano/projects/basic_test
98
+
99
+ You can run MurCLI commands now, but they won't be useful until you ``init``. E.g.,
100
+
101
+ .. code-block:: text
102
+
103
+ $ murano show
104
+
105
+ No Murano user account found.
106
+ Please login using `murano login` or `murano init`.
107
+ Or set your password with `murano password set <username>`.
108
+
109
+ Run the init command to easily wire the new project to your existing business,
110
+ to create an Application and Product, and to setup local directories and files.
111
+
112
+ The init command will link the Product to the Application so that data sent
113
+ to the Product is passed along to the Application.
114
+
115
+ Here's an example use of the init command.
116
+
117
+ .. code-block:: text
118
+
119
+ $ murano init
120
+
121
+ Creating project at /user/home/murano/projects/basic_test
122
+
123
+ No Murano user account found. Please login.
124
+ User name: exositement@exosite.com
125
+ Password: *************
126
+ 1. My First Business 2. Collaborative Biz 3. Another of My Biz
127
+ Please select the Business to use:
128
+ 3
129
+
130
+ This business does not have any applications. Let's create one
131
+
132
+ Please enter the Application name: basicexample
133
+
134
+ Created new Application: basicexample <v3sl941hifticggc0>
135
+
136
+ This business does not have any products. Let's create one
137
+
138
+ Please enter the Product name: exampleprod
139
+
140
+ Created new Product: exampleprod <n51cq3fea5zc40cs4>
141
+
142
+ Linked ‘exampleprod’ to ‘basicexample’
143
+
144
+ Created default event handler
145
+
146
+ Writing Project file to basictest.murano
147
+
148
+ Created default directories
149
+
150
+ Synced 4 items
151
+
152
+ Success!
153
+
154
+ Business ID: ct7rmoz3hu34ygb9
155
+ Application ID: v3sl941hifticggc0
156
+ Product ID: n51cq3fea5zc40cs4
157
+
158
+ You'll notice that ``init`` downloaded a few files from Murano that are
159
+ automatically created when you create solutions and link them.
160
+
161
+ For instance, you should see a handful of Lua scripts in the ``services``
162
+ directory.
163
+
164
+ .. code-block:: text
165
+
166
+ $ ls services
167
+
168
+ n51cq3fea5zc40cs4_event.lua timer_timer.lua tsdb_exportJob.lua user_account.lua
169
+
170
+ Update the Data Event Handler
171
+ =============================
172
+
173
+ Let's edit the Product data event handler so that it spits out a log message
174
+ when it gets data from the Product. The event handler is named using the
175
+ Product ID, so grab that, and use the ID to make the name of the Lua script.
176
+
177
+ .. code-block:: text
178
+
179
+ $ PRODUCT_ID=$(murano config product.id)
180
+
181
+ $ PROD_EVENT="services/${PRODUCT_ID}_event.lua"
182
+
183
+ $ echo ${PROD_EVENT}
184
+
185
+ services/n51cq3fea5zc40cs4_event.lua
186
+
187
+ You'll notice that Murano already created a simple event handler.
188
+
189
+ .. code-block:: text
190
+
191
+ $ cat ${PROD_EVENT}
192
+
193
+ --#EVENT n51cq3fea5zc40cs4 event
194
+ print(event)
195
+
196
+ Now, overwrite the event handler with something similar. We just
197
+ want to show how easy it is to update the event handler.
198
+
199
+ .. code-block:: text
200
+
201
+ $ cat > ${PROD_EVENT} << EOF
202
+ --#EVENT ${PRODUCT_ID} event
203
+ print("EVENT: " .. to_json(event))
204
+ EOF
205
+
206
+ NOTE: The ``--#EVENT`` header is mandatory. It tells Murano
207
+ how to interpret the snippet of Lua code.
208
+
209
+ If you run the ``status`` command, you should see that there's now one
210
+ file modified locally (the event handler that we just edited) that is
211
+ not synced with the corresponding event handler on Murano.
212
+
213
+ .. code-block:: text
214
+
215
+ $ murano status
216
+
217
+ Nothing new locally
218
+ Nothing new remotely
219
+ Items that differ:
220
+ M E services/n51cq3fea5zc40cs4_event.lua
221
+
222
+ Run the ``syncup`` command to upload any modified files to Murano,
223
+ overwriting what is on Murano.
224
+
225
+ .. code-block:: text
226
+
227
+ $ murano syncup
228
+
229
+ Create and Provision a New Device
230
+ =================================
231
+
232
+ In order to do something useful, we need to create a device,
233
+ that is attached to the Product, that can generate data.
234
+
235
+ You'll notice that the new Product does not have any devices.
236
+
237
+ .. code-block:: text
238
+
239
+ $ murano device list
240
+
241
+ Did not find any devices
242
+
243
+ Create a device. We can use whatever identifier we want, so
244
+ just grab a random UUID.
245
+
246
+ .. code-block:: text
247
+
248
+ $ SOME_ID=$(uuidgen)
249
+
250
+ $ murano device enable ${SOME_ID}
251
+
252
+ $ murano device list
253
+
254
+ +--------------------------------------+-------------+--------+
255
+ | Identifier | Status | Online |
256
+ +--------------------------------------+-------------+--------+
257
+ | 1af384dd-57ba-4f13-9d89-45dbcbf207de | whitelisted | false |
258
+ +--------------------------------------+-------------+--------+
259
+
260
+ Provision the device. Murano generates and returns a CIK
261
+ that we need to remember so that we can authenticate as
262
+ the device when making calls on its behalf.
263
+
264
+ .. code-block:: text
265
+
266
+ $ CIK=$(murano product device activate ${SOME_ID})
267
+
268
+ $ echo ${CIK}
269
+
270
+ MJzNuMqPDs7UADLriMlHK10dClv7cx46uLSkJLSw
271
+
272
+ $ murano device list
273
+
274
+ +--------------------------------------+-------------+--------+
275
+ | Identifier | Status | Online |
276
+ +--------------------------------------+-------------+--------+
277
+ | 1af384dd-57ba-4f13-9d89-45dbcbf207de | provisioned | false |
278
+ +--------------------------------------+-------------+--------+
279
+
280
+ Generate Device Data
281
+ ====================
282
+
283
+ Each solution (Application or Product) has its own URI.
284
+ We need the Product's URI in order to interact with Murano
285
+ on behalf of the device.
286
+
287
+ Make a local variable for the Product URI.
288
+
289
+ .. code-block:: text
290
+
291
+ $ PRODUCT_URI=$(murano domain product --brief --no-progress)
292
+
293
+ NOTE: We need to use the ``--no-progress`` option, otherwise MurCLI
294
+ will display a progress bar that contaminates the captured output.
295
+
296
+ Write data to the device. E.g., let's write a very cold temperature value.
297
+
298
+ .. code-block:: text
299
+
300
+ $ curl -si -k https://${PRODUCT_URI}/onep:v1/stack/alias \
301
+ -H "X-Exosite-CIK: ${CIK}" \
302
+ -H "Accept: application/x-www-form-urlencoded; charset=utf-8" \
303
+ -d reports='{"temperature": -40.0}' \
304
+ -i -v -w "%{http_code}"
305
+
306
+ [VERBOSE OUTPUT OMITTED]
307
+ 204
308
+
309
+ Verify that the data was passed from the Product to the Application and
310
+ processed how we indicated in the event handler (which is to log it).
311
+
312
+ .. code-block:: text
313
+
314
+ $ murano logs --application
315
+
316
+ DEBUG [n51cq3fea5zc40cs4_event] 2017-07-26T11:44:57.000-05:00:
317
+ EVENT: {
318
+ "connection_id":"D2bzFD6HSV3ih56dbswY",
319
+ "identity":"1af384dd-57ba-4f13-9d89-45dbcbf207de",
320
+ "ip":"123.234.012.234",
321
+ "protocol":"onep",
322
+ "timestamp":1.501087497424287e+15,
323
+ "type":"provisioned"
324
+ }
325
+
326
+ DEBUG [n51cq3fea5zc40cs4_event] 2017-07-26T14:09:30.000-05:00:
327
+ EVENT: {
328
+ "connection_id":"QWJeZcpXej5h5f5hwdLY",
329
+ "identity":"1af384dd-57ba-4f13-9d89-45dbcbf207de",
330
+ "ip":"123.234.012.234",
331
+ "payload":[{
332
+ "timestamp":1.501096170486053e+15,
333
+ "values":{
334
+ "reports":"{\"temperature\": -40.0}"}
335
+ }],
336
+ "protocol":"onep",
337
+ "timestamp":1.501096170487898e+15,
338
+ "type":"data_in"
339
+ }
340
+
341
+ Success! You should see the ``temperature`` value in the last log message.
342
+
343
+ You'll notice that the Product does not generate any log messages.
344
+
345
+ .. code-block:: text
346
+
347
+ $ murano logs --product
348
+
349
+ # [NO OUTPUT]
350
+
351
+ Create a Resource
352
+ =================
353
+
354
+ Bonus step! Create a resource for your data.
355
+
356
+ NOTE: The write operation works regardless of having a resource defined.
357
+
358
+ Create a resources file that describes the data. E.g.,
359
+
360
+ .. code-block:: text
361
+
362
+ $ cat > specs/resources.yaml << EOF
363
+ ---
364
+ temperature:
365
+ allowed: []
366
+ format: number
367
+ settable: false
368
+ unit: ''
369
+ EOF
370
+
371
+ Upload the resources to Murano.
372
+
373
+ .. code-block:: text
374
+
375
+ $ murano syncup
376
+
377
+ And write more data.
378
+
379
+ .. code-block:: text
380
+
381
+ $ curl -si -k https://${PRODUCT_URI}/onep:v1/stack/alias \
382
+ -H "X-Exosite-CIK: ${CIK}" \
383
+ -H "Accept: application/x-www-form-urlencoded; charset=utf-8" \
384
+ -d raw_data='{"temperature": -19.9}' \
385
+ -i -v -w "%{http_code}"
386
+
387
+ Verify that you see a new event in the log.
388
+
389
+ .. code-block:: text
390
+
391
+ $ murano logs --application
392
+
393
+ DEBUG [n51cq3fea5zc40cs4_event] 2017-07-26T11:44:57.000-05:00:
394
+ EVENT: {
395
+ "connection_id":"D2bzFD6HSV3ih56dbswY",
396
+ "identity":"1af384dd-57ba-4f13-9d89-45dbcbf207de",
397
+ "ip":"123.234.012.234",
398
+ "protocol":"onep",
399
+ "timestamp":1.501087497424287e+15,
400
+ "type":"provisioned"
401
+ }
402
+
403
+ DEBUG [n51cq3fea5zc40cs4_event] 2017-07-26T14:09:30.000-05:00:
404
+ EVENT: {
405
+ "connection_id":"QWJeZcpXej5h5f5hwdLY",
406
+ "identity":"1af384dd-57ba-4f13-9d89-45dbcbf207de",
407
+ "ip":"123.234.012.234",
408
+ "payload":[{
409
+ "timestamp":1.501096170486053e+15,
410
+ "values":{
411
+ "reports":"{\"temperature\": -40.0}"}
412
+ }],
413
+ "protocol":"onep",
414
+ "timestamp":1.501096170487898e+15,
415
+ "type":"data_in"
416
+ }
417
+
418
+ DEBUG [n51cq3fea5zc40cs4_event] 2017-07-26T14:16:00.000-05:00:
419
+ EVENT: {
420
+ "connection_id":"3DD9rAZ95bgro5O0kGGD",
421
+ "identity":"1af384dd-57ba-4f13-9d89-45dbcbf207de",
422
+ "ip":"123.234.012.234",
423
+ "payload":[{
424
+ "timestamp":1.501096560116624e+15,
425
+ "values":{
426
+ "raw_data":"{\"temperature\": -19.9}"}
427
+ }],
428
+ "protocol":"onep",
429
+ "timestamp":1.501096560118335e+15,
430
+ "type":"data_in"
431
+ }
432
+
433
+ *Et Voilà!*
434
+
435
+ Congratulations of your first, very basic Murano project!
436
+