MuranoCLI 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +28 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +21 -0
  5. data/Gemfile +27 -0
  6. data/LICENSE.txt +19 -0
  7. data/MuranoCLI.gemspec +50 -0
  8. data/MuranoCLI.iss +50 -0
  9. data/README.markdown +208 -0
  10. data/Rakefile +188 -0
  11. data/TODO.taskpaper +122 -0
  12. data/bin/mr +8 -0
  13. data/bin/murano +84 -0
  14. data/docs/demo.md +109 -0
  15. data/lib/MrMurano/Account.rb +211 -0
  16. data/lib/MrMurano/Config-Migrate.rb +47 -0
  17. data/lib/MrMurano/Config.rb +286 -0
  18. data/lib/MrMurano/Mock.rb +63 -0
  19. data/lib/MrMurano/Product-1P-Device.rb +145 -0
  20. data/lib/MrMurano/Product-Resources.rb +195 -0
  21. data/lib/MrMurano/Product.rb +358 -0
  22. data/lib/MrMurano/ProjectFile.rb +349 -0
  23. data/lib/MrMurano/Solution-Cors.rb +46 -0
  24. data/lib/MrMurano/Solution-Endpoint.rb +177 -0
  25. data/lib/MrMurano/Solution-File.rb +150 -0
  26. data/lib/MrMurano/Solution-ServiceConfig.rb +140 -0
  27. data/lib/MrMurano/Solution-Services.rb +326 -0
  28. data/lib/MrMurano/Solution-Users.rb +129 -0
  29. data/lib/MrMurano/Solution.rb +59 -0
  30. data/lib/MrMurano/SubCmdGroupContext.rb +49 -0
  31. data/lib/MrMurano/SyncUpDown.rb +565 -0
  32. data/lib/MrMurano/commands/assign.rb +57 -0
  33. data/lib/MrMurano/commands/businessList.rb +45 -0
  34. data/lib/MrMurano/commands/completion.rb +152 -0
  35. data/lib/MrMurano/commands/config.rb +67 -0
  36. data/lib/MrMurano/commands/content.rb +130 -0
  37. data/lib/MrMurano/commands/cors.rb +30 -0
  38. data/lib/MrMurano/commands/domain.rb +17 -0
  39. data/lib/MrMurano/commands/gb.rb +33 -0
  40. data/lib/MrMurano/commands/init.rb +138 -0
  41. data/lib/MrMurano/commands/keystore.rb +157 -0
  42. data/lib/MrMurano/commands/logs.rb +78 -0
  43. data/lib/MrMurano/commands/mock.rb +63 -0
  44. data/lib/MrMurano/commands/password.rb +88 -0
  45. data/lib/MrMurano/commands/postgresql.rb +41 -0
  46. data/lib/MrMurano/commands/product.rb +14 -0
  47. data/lib/MrMurano/commands/productCreate.rb +39 -0
  48. data/lib/MrMurano/commands/productDelete.rb +33 -0
  49. data/lib/MrMurano/commands/productDevice.rb +84 -0
  50. data/lib/MrMurano/commands/productDeviceIdCmds.rb +86 -0
  51. data/lib/MrMurano/commands/productList.rb +45 -0
  52. data/lib/MrMurano/commands/productWrite.rb +27 -0
  53. data/lib/MrMurano/commands/show.rb +80 -0
  54. data/lib/MrMurano/commands/solution.rb +14 -0
  55. data/lib/MrMurano/commands/solutionCreate.rb +39 -0
  56. data/lib/MrMurano/commands/solutionDelete.rb +34 -0
  57. data/lib/MrMurano/commands/solutionList.rb +45 -0
  58. data/lib/MrMurano/commands/status.rb +92 -0
  59. data/lib/MrMurano/commands/sync.rb +60 -0
  60. data/lib/MrMurano/commands/timeseries.rb +115 -0
  61. data/lib/MrMurano/commands/tsdb.rb +271 -0
  62. data/lib/MrMurano/commands/usage.rb +23 -0
  63. data/lib/MrMurano/commands/zshcomplete.erb +112 -0
  64. data/lib/MrMurano/commands.rb +32 -0
  65. data/lib/MrMurano/hash.rb +20 -0
  66. data/lib/MrMurano/http.rb +153 -0
  67. data/lib/MrMurano/makePretty.rb +75 -0
  68. data/lib/MrMurano/schema/pf-v1.0.0.yaml +114 -0
  69. data/lib/MrMurano/schema/sf-v0.2.0.yaml +77 -0
  70. data/lib/MrMurano/schema/sf-v0.3.0.yaml +78 -0
  71. data/lib/MrMurano/template/mock.erb +9 -0
  72. data/lib/MrMurano/template/projectFile.murano.erb +81 -0
  73. data/lib/MrMurano/verbosing.rb +99 -0
  74. data/lib/MrMurano/version.rb +4 -0
  75. data/lib/MrMurano.rb +20 -0
  76. data/spec/Account-Passwords_spec.rb +242 -0
  77. data/spec/Account_spec.rb +272 -0
  78. data/spec/ConfigFile_spec.rb +50 -0
  79. data/spec/ConfigMigrate_spec.rb +89 -0
  80. data/spec/Config_spec.rb +409 -0
  81. data/spec/Http_spec.rb +204 -0
  82. data/spec/MakePretties_spec.rb +118 -0
  83. data/spec/Mock_spec.rb +53 -0
  84. data/spec/ProductBase_spec.rb +113 -0
  85. data/spec/ProductContent_spec.rb +162 -0
  86. data/spec/ProductResources_spec.rb +329 -0
  87. data/spec/Product_1P_Device_spec.rb +202 -0
  88. data/spec/Product_1P_RPC_spec.rb +175 -0
  89. data/spec/Product_spec.rb +153 -0
  90. data/spec/ProjectFile_spec.rb +324 -0
  91. data/spec/Solution-Cors_spec.rb +164 -0
  92. data/spec/Solution-Endpoint_spec.rb +581 -0
  93. data/spec/Solution-File_spec.rb +212 -0
  94. data/spec/Solution-ServiceConfig_spec.rb +202 -0
  95. data/spec/Solution-ServiceDevice_spec.rb +176 -0
  96. data/spec/Solution-ServiceEventHandler_spec.rb +385 -0
  97. data/spec/Solution-ServiceModules_spec.rb +465 -0
  98. data/spec/Solution-UsersRoles_spec.rb +207 -0
  99. data/spec/Solution_spec.rb +92 -0
  100. data/spec/SyncRoot_spec.rb +83 -0
  101. data/spec/SyncUpDown_spec.rb +495 -0
  102. data/spec/Verbosing_spec.rb +279 -0
  103. data/spec/_workspace.rb +27 -0
  104. data/spec/cmd_assign_spec.rb +51 -0
  105. data/spec/cmd_business_spec.rb +59 -0
  106. data/spec/cmd_common.rb +72 -0
  107. data/spec/cmd_config_spec.rb +68 -0
  108. data/spec/cmd_content_spec.rb +71 -0
  109. data/spec/cmd_cors_spec.rb +50 -0
  110. data/spec/cmd_device_spec.rb +96 -0
  111. data/spec/cmd_domain_spec.rb +32 -0
  112. data/spec/cmd_init_spec.rb +30 -0
  113. data/spec/cmd_keystore_spec.rb +97 -0
  114. data/spec/cmd_password_spec.rb +62 -0
  115. data/spec/cmd_status_spec.rb +239 -0
  116. data/spec/cmd_syncdown_spec.rb +86 -0
  117. data/spec/cmd_syncup_spec.rb +62 -0
  118. data/spec/cmd_usage_spec.rb +36 -0
  119. data/spec/fixtures/.mrmuranorc +9 -0
  120. data/spec/fixtures/ProjectFiles/invalid.yaml +9 -0
  121. data/spec/fixtures/ProjectFiles/only_meta.yaml +24 -0
  122. data/spec/fixtures/ProjectFiles/with_routes.yaml +27 -0
  123. data/spec/fixtures/SolutionFiles/0.2.0.json +20 -0
  124. data/spec/fixtures/SolutionFiles/0.2.0_invalid.json +18 -0
  125. data/spec/fixtures/SolutionFiles/0.2.json +21 -0
  126. data/spec/fixtures/SolutionFiles/0.3.0.json +20 -0
  127. data/spec/fixtures/SolutionFiles/0.3.0_invalid.json +19 -0
  128. data/spec/fixtures/SolutionFiles/0.3.json +20 -0
  129. data/spec/fixtures/SolutionFiles/basic.json +20 -0
  130. data/spec/fixtures/SolutionFiles/secret.json +6 -0
  131. data/spec/fixtures/configfile +9 -0
  132. data/spec/fixtures/dumped_config +42 -0
  133. data/spec/fixtures/mrmuranorc_deleted_bob +8 -0
  134. data/spec/fixtures/mrmuranorc_tool_bob +3 -0
  135. data/spec/fixtures/product_spec_files/example.exoline.spec.yaml +116 -0
  136. data/spec/fixtures/product_spec_files/example.murano.spec.yaml +14 -0
  137. data/spec/fixtures/product_spec_files/gwe.exoline.spec.yaml +21 -0
  138. data/spec/fixtures/product_spec_files/gwe.murano.spec.yaml +16 -0
  139. data/spec/fixtures/product_spec_files/lightbulb-no-state.yaml +11 -0
  140. data/spec/fixtures/product_spec_files/lightbulb.yaml +14 -0
  141. data/spec/fixtures/roles-three.yaml +11 -0
  142. data/spec/fixtures/syncable_content/assets/icon.png +0 -0
  143. data/spec/fixtures/syncable_content/assets/index.html +0 -0
  144. data/spec/fixtures/syncable_content/assets/js/script.js +0 -0
  145. data/spec/fixtures/syncable_content/modules/table_util.lua +58 -0
  146. data/spec/fixtures/syncable_content/routes/manyRoutes.lua +11 -0
  147. data/spec/fixtures/syncable_content/routes/singleRoute.lua +5 -0
  148. data/spec/fixtures/syncable_content/services/devdata.lua +18 -0
  149. data/spec/fixtures/syncable_content/services/timers.lua +4 -0
  150. data/spec/spec_helper.rb +119 -0
  151. metadata +498 -0
@@ -0,0 +1,78 @@
1
+ ---
2
+ type: object
3
+ description: |
4
+ A Solutionfile.json
5
+ This describes all of the bits and bobs that go into a Murano Solution.
6
+
7
+ properties:
8
+ version:
9
+ type: string
10
+ pattern: "0\\.3(\\.0)?"
11
+ description: Version format of the config
12
+
13
+ default_page:
14
+ type: string
15
+ description: The local file name to upload as /
16
+
17
+ assets:
18
+ type: string
19
+ description: Relative path to directory of static assets
20
+
21
+ routes:
22
+ type: string
23
+ description: Relative path of file containing endpoints (or routes)
24
+
25
+ routes_hook:
26
+ type: string
27
+ description: URL path to call at end of deploy
28
+
29
+ modules:
30
+ type: object
31
+ description: Additional lua chunks to load with endpoints and event handlers
32
+ patternProperties:
33
+ "[a-z]+":
34
+ type: string
35
+ description: Relative path to module script
36
+
37
+ services:
38
+ type: object
39
+ description: Event handler scripts
40
+ properties:
41
+ device:
42
+ type: object
43
+ description: Device (Product) event handlers
44
+ properties:
45
+ datapoint:
46
+ type: string
47
+ description: Relative path to device.datapoint event script
48
+ required: [datapoint]
49
+ timer:
50
+ type: object
51
+ description: Timer event handlers
52
+ properties:
53
+ timer:
54
+ type: string
55
+ description: Relative path to timer.timer event script
56
+ required: [timer]
57
+ additionalProperties: false
58
+
59
+ cors:
60
+ type: object
61
+ properties:
62
+ origin:
63
+ type: array
64
+ methods:
65
+ type: array
66
+ headers:
67
+ type: array
68
+ credentials:
69
+ type: boolean
70
+
71
+ required:
72
+ - default_page
73
+ - assets
74
+ - routes
75
+ - services
76
+ - version
77
+ additionalProperties: false
78
+
@@ -0,0 +1,9 @@
1
+ --#ENDPOINT POST /testpoint/{service}/{call}
2
+ -- this function allows remote calls to your services
3
+ if request.headers["authorization"] == "<%= uuid %>" then
4
+ local fn = _G[request.parameters.service][request.parameters.call]
5
+ response.message = fn(request.body)
6
+ else
7
+ response.code = 401
8
+ response.message = "invalid authorization header"
9
+ end
@@ -0,0 +1,81 @@
1
+ ---
2
+ # First up is some metadata about this project.
3
+ info:
4
+ # Nice short and easy. Also must be a valid domain name component.
5
+ name: <%= info.name %>
6
+
7
+ # Short one line summary of this project.
8
+ summary: <%= info.summary %>
9
+
10
+ # Longer, multiple paragraph explanation.
11
+ description: |
12
+ <%= info.description.gsub(/^/m, ' ') %>
13
+
14
+ # Who made this
15
+ authors: <%= info.authors.to_json %>
16
+
17
+ # The version of the Project
18
+ version: <%= info.version %>
19
+
20
+
21
+ ####
22
+ #
23
+ # The sections routes, assets, modules, and services are all optional.
24
+ #
25
+ # They all have defaults values that should work for a majority of the projects out
26
+ # there. But they are all fully configurable to fit the way you want your project
27
+ # to be.
28
+ #
29
+ # Examples follow.
30
+ #
31
+ #
32
+ #routes:
33
+ # #Start off with the directory name we want to keep everything in.
34
+ # location: routes
35
+ #
36
+ # #Then use globs to find all of the files that can contain route code.
37
+ # #If using single glob, then can be just the string.
38
+ # include: ['{,../endpoints}/*.lua', '{,../endpoints}/*/*.lua']
39
+ # #include: '**/*.lua'
40
+ #
41
+ # #Then remove all that match these globs. Again, if a single, can drop the array.
42
+ # #If not excluding, use empty array [], or empty node.
43
+ # exclude: ['*_test.lua', '*_spec.lua', '**/.*']
44
+ #
45
+ # #That leaves a list of files with API routes in them. Each Route file can
46
+ # #contain one or more actual routes that are synced with Murano.
47
+ #
48
+ #
49
+ # #If you are hosting your website somewhere other than on Murano, and you want to
50
+ # #tighten up what Cross Origin calls are allowed, you can set that here.
51
+ #
52
+ # #Either point to a YAML file
53
+ # cors: "cors.yaml"
54
+ # #Or include it directly
55
+ # cors: {"origin":true,"methods":["HEAD","GET","POST","PUT","DELETE","OPTIONS","PATCH"],"headers":["Content-Type","Cookie","Authorization"],"credentials":true}
56
+ #
57
+ #assets:
58
+ # location: assets
59
+ # include: '**/*'
60
+ # exclude:
61
+ # default_page: index.html
62
+ #
63
+ #modules:
64
+ # location: modules
65
+ # include: ['*.lua', '*/*.lua']
66
+ # exclude: ['*_test.lua', '*_spec.lua', '**/.*']
67
+ #
68
+ #services:
69
+ # location: services
70
+ # include:
71
+ # - '*.lua'
72
+ # - '*/*.lua'
73
+ # - '{../eventhandlers,../event_handler}/*.lua'
74
+ # - '{../eventhandlers,../event_handler}/*/*.lua'
75
+ # exclude: ['*_test.lua', '*_spec.lua', '**/.*']
76
+
77
+
78
+ # The format version of this file. This is required.
79
+ formatversion: 1.0.0
80
+
81
+ # vim: set et sw=2 ts=2 :
@@ -0,0 +1,99 @@
1
+ require 'highline'
2
+ require 'yaml'
3
+ require 'json'
4
+ require 'pp'
5
+ require 'csv'
6
+ require 'terminal-table'
7
+
8
+ module MrMurano
9
+ module Verbose
10
+ def verbose(msg)
11
+ if $cfg['tool.verbose'] then
12
+ say msg
13
+ end
14
+ end
15
+
16
+ def debug(msg)
17
+ if $cfg['tool.debug'] then
18
+ say msg
19
+ end
20
+ end
21
+
22
+ def warning(msg)
23
+ $stderr.puts HighLine.color(msg, :yellow)
24
+ end
25
+
26
+ def error(msg)
27
+ $stderr.puts HighLine.color(msg, :red)
28
+ end
29
+
30
+ ## Output tabular data
31
+ # +data+:: Data to write. Preferably a Hash with :headers and :rows
32
+ # +ios+:: Output stream to write to, if nil, then use $stdout
33
+ # Output is either a nice visual table or CSV.
34
+ def tabularize(data, ios=nil)
35
+ fmt = $cfg['tool.outformat']
36
+ ios = $stdout if ios.nil?
37
+ cols = nil
38
+ rows = nil
39
+ title = nil
40
+ if data.kind_of?(Hash) then
41
+ cols = data[:headers] if data.has_key?(:headers)
42
+ rows = data[:rows] if data.has_key?(:rows)
43
+ title = data[:title]
44
+ elsif data.kind_of?(Array) then
45
+ rows = data
46
+ elsif data.respond_to?(:to_a) then
47
+ rows = data.to_a
48
+ elsif data.respond_to?(:each) then
49
+ rows = []
50
+ data.each{|i| rows << i}
51
+ else
52
+ error "Don't know how to tabularize data."
53
+ return
54
+ end
55
+ if fmt =~ /csv/i then
56
+ cols = [] if cols.nil?
57
+ rows = [[]] if rows.nil?
58
+ CSV(ios, :headers=>cols, :write_headers=>(not cols.empty?)) do |csv|
59
+ rows.each{|v| csv << v}
60
+ end
61
+ else
62
+ # table.
63
+ table = Terminal::Table.new
64
+ table.title = title unless title.nil?
65
+ table.headings = cols unless cols.nil?
66
+ table.rows = rows unless rows.nil?
67
+ ios.puts table
68
+ end
69
+ end
70
+
71
+ ## Format and print the object
72
+ # Handles many of the raw 'unpolished' formats.
73
+ def outf(obj, ios=nil, &block)
74
+ fmt = $cfg['tool.outformat']
75
+ ios = $stdout if ios.nil?
76
+ case fmt
77
+ when /yaml/i
78
+ ios.puts Hash.transform_keys_to_strings(obj).to_yaml
79
+ when /pp/
80
+ pp obj
81
+ when /json/i
82
+ ios.puts obj.to_json
83
+ else # aka best.
84
+ # sometime ‘best’ is only know by the caller, so block.
85
+ if block_given? then
86
+ yield obj, ios
87
+ else
88
+ if obj.kind_of?(Array) then
89
+ obj.each {|i| ios.puts i.to_s}
90
+ else
91
+ ios.puts obj.to_s
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ end
98
+ end
99
+ # vim: set ai et sw=2 ts=2 :
@@ -0,0 +1,4 @@
1
+ module MrMurano
2
+ VERSION = '2.0.0'.freeze
3
+ end
4
+
data/lib/MrMurano.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'MrMurano/version'
2
+ require 'MrMurano/verbosing'
3
+ require 'MrMurano/hash'
4
+ require 'MrMurano/http'
5
+
6
+ require 'MrMurano/Config'
7
+ require 'MrMurano/ProjectFile'
8
+
9
+ require 'MrMurano/Account'
10
+ require 'MrMurano/Solution'
11
+ require 'MrMurano/Solution-Endpoint'
12
+ require 'MrMurano/Solution-File'
13
+ require 'MrMurano/Solution-Services'
14
+ require 'MrMurano/Solution-Users'
15
+ require 'MrMurano/Solution-ServiceConfig'
16
+ require 'MrMurano/Product'
17
+ require 'MrMurano/Product-1P-Device'
18
+ require 'MrMurano/Product-Resources'
19
+
20
+ require 'MrMurano/commands'
@@ -0,0 +1,242 @@
1
+ require 'MrMurano/version'
2
+ require 'MrMurano/Account'
3
+ require 'tempfile'
4
+
5
+ RSpec.describe MrMurano::Passwords, "#pwd" do
6
+ before(:example) do
7
+ @saved_pwd = ENV['MURANO_PASSWORD']
8
+ ENV['MURANO_PASSWORD'] = nil
9
+ end
10
+ after(:example) do
11
+ ENV['MURANO_PASSWORD'] = @saved_pwd
12
+ end
13
+
14
+ it "Creates a file " do
15
+ tmpfile = Dir.tmpdir + '/pwtest' # This way because Tempfile.new creates.
16
+ begin
17
+ pwd = MrMurano::Passwords.new( tmpfile )
18
+ pwd.save
19
+
20
+ expect( FileTest.exist?(tmpfile) )
21
+ ensure
22
+ File.unlink(tmpfile) if File.exist? tmpfile
23
+ end
24
+ end
25
+
26
+ it "Creates a file in a directory that doesn't exist." do
27
+ tmpfile = Dir.tmpdir + '/deeper/pwtest' # This way because Tempfile.new creates.
28
+ begin
29
+ pwd = MrMurano::Passwords.new( tmpfile )
30
+ pwd.save
31
+
32
+ expect( FileTest.exist?(tmpfile) )
33
+ ensure
34
+ File.unlink(tmpfile) if File.exist? tmpfile
35
+ end
36
+ end
37
+
38
+ it "Loads a file" do
39
+ Tempfile.open('test') do |tf|
40
+ tf << %{---
41
+ this.is.a.host:
42
+ user: password
43
+ }
44
+ tf.close
45
+
46
+ pwd = MrMurano::Passwords.new( tf.path )
47
+ pwd.load
48
+ ps = pwd.get('this.is.a.host', 'user')
49
+ expect(ps).to eq('password')
50
+ end
51
+ end
52
+
53
+ it "Saves a file" do
54
+ Tempfile.open('pstest') do |tf|
55
+ tf.close
56
+
57
+ pwd = MrMurano::Passwords.new(tf.path)
58
+ pwd.set('this.is.a.host', 'user3', 'passwords4')
59
+ pwd.save
60
+
61
+ File.open(tf.path) do |io|
62
+ data = io.read
63
+ expect(data).to eq(%{---
64
+ this.is.a.host:
65
+ user3: passwords4
66
+ })
67
+ end
68
+ end
69
+ end
70
+
71
+ it "Writes multiple hosts" do
72
+ Tempfile.open('pwtest') do |tf|
73
+ tf.close
74
+
75
+ pwd = MrMurano::Passwords.new(tf.path)
76
+ pwd.set('this.is.a.host', 'user3', 'passwords4')
77
+ pwd.save
78
+ pwd = nil
79
+
80
+ pwd = MrMurano::Passwords.new(tf.path)
81
+ pwd.load
82
+ ps = pwd.get('this.is.a.host', 'user3')
83
+ expect(ps).to eq('passwords4')
84
+ pwd = nil
85
+
86
+ pwd = MrMurano::Passwords.new(tf.path)
87
+ pwd.load
88
+ pwd.set('another.host', 'user9', 'passwords2')
89
+ pwd.save
90
+ pwd = nil
91
+
92
+ pwd = MrMurano::Passwords.new(tf.path)
93
+ pwd.load
94
+ ps = pwd.get('this.is.a.host', 'user3')
95
+ expect(ps).to eq('passwords4')
96
+ ps = pwd.get('another.host', 'user9')
97
+ expect(ps).to eq('passwords2')
98
+ pwd = nil
99
+
100
+ end
101
+ end
102
+
103
+ it "Write multiple users to same host" do
104
+ Tempfile.open('pwstest') do |tf|
105
+ tf.close
106
+
107
+ pwd = MrMurano::Passwords.new(tf.path)
108
+ pwd.set('this.is.a.host', 'user3', 'passwords4')
109
+ pwd.save
110
+ pwd = nil
111
+
112
+ pwd = MrMurano::Passwords.new(tf.path)
113
+ pwd.load
114
+ pwd.set('this.is.a.host', 'user9', 'passwords2')
115
+ pwd.save
116
+ pwd = nil
117
+
118
+ pwd = MrMurano::Passwords.new(tf.path)
119
+ pwd.load
120
+ ps = pwd.get('this.is.a.host', 'user3')
121
+ expect(ps).to eq('passwords4')
122
+ ps = pwd.get('this.is.a.host', 'user9')
123
+ expect(ps).to eq('passwords2')
124
+ pwd = nil
125
+
126
+ end
127
+ end
128
+
129
+ it "lists usernames" do
130
+ Tempfile.open('pwstest') do |tf|
131
+ tf.close
132
+
133
+ pwd = MrMurano::Passwords.new(tf.path)
134
+ pwd.set('this.is.a.host', 'user3', 'passwords4')
135
+ pwd.save
136
+ pwd = nil
137
+
138
+ pwd = MrMurano::Passwords.new(tf.path)
139
+ pwd.load
140
+ pwd.set('this.is.a.host', 'user9', 'passwords2')
141
+ pwd.save
142
+ pwd = nil
143
+
144
+ pwd = MrMurano::Passwords.new(tf.path)
145
+ pwd.load
146
+ ret = pwd.list
147
+ expect(ret).to match({
148
+ "this.is.a.host"=>a_collection_containing_exactly("user9", "user3")
149
+ })
150
+ end
151
+ end
152
+
153
+
154
+ it "removes username" do
155
+ Tempfile.open('pwstest') do |tf|
156
+ tf.close
157
+
158
+ pwd = MrMurano::Passwords.new(tf.path)
159
+ pwd.set('this.is.a.host', 'user3', 'passwords4')
160
+ pwd.save
161
+ pwd = nil
162
+
163
+ pwd = MrMurano::Passwords.new(tf.path)
164
+ pwd.load
165
+ pwd.set('this.is.a.host', 'user9', 'passwords2')
166
+ pwd.save
167
+ pwd = nil
168
+
169
+ pwd = MrMurano::Passwords.new(tf.path)
170
+ pwd.load
171
+ pwd.remove('this.is.a.host', 'user3')
172
+ pwd.save
173
+ pwd = nil
174
+
175
+ pwd = MrMurano::Passwords.new(tf.path)
176
+ pwd.load
177
+ ret = pwd.list
178
+ expect(ret).to match({ "this.is.a.host"=>["user9"] })
179
+ end
180
+ end
181
+
182
+ context "Uses ENV" do
183
+ before(:example) do
184
+ ENV['MR_PASSWORD'] = nil
185
+ end
186
+ after(:example) do
187
+ ENV['MR_PASSWORD'] = nil
188
+ end
189
+
190
+ it "Uses ENV instead" do
191
+ Tempfile.open('test') do |tf|
192
+ tf << %{---
193
+ this.is.a.host:
194
+ user: password
195
+ }
196
+ tf.close
197
+
198
+ ENV['MURANO_PASSWORD'] = 'a test!'
199
+ pwd = MrMurano::Passwords.new( tf.path )
200
+ pwd.load
201
+ expect(pwd).not_to receive(:warning)
202
+ ps = pwd.get('this.is.a.host', 'user')
203
+ expect(ps).to eq('a test!')
204
+ ENV['MURANO_PASSWORD'] = nil
205
+ end
206
+ end
207
+
208
+ it "Uses ENV instead, even with empty file" do
209
+ Tempfile.open('test') do |tf|
210
+ tf.close
211
+
212
+ ENV['MURANO_PASSWORD'] = 'a test!'
213
+ pwd = MrMurano::Passwords.new( tf.path )
214
+ pwd.load
215
+ expect(pwd).not_to receive(:warning)
216
+ ps = pwd.get('this.is.a.host', 'user')
217
+ expect(ps).to eq('a test!')
218
+ ENV['MURANO_PASSWORD'] = nil
219
+
220
+ data = IO.read(tf.path)
221
+ expect(data).to eq('')
222
+ end
223
+ end
224
+
225
+ it "Warns about migrating" do
226
+ Tempfile.open('test') do |tf|
227
+ tf.close
228
+
229
+ ENV['MR_PASSWORD'] = 'a test!'
230
+ pwd = MrMurano::Passwords.new( tf.path )
231
+ pwd.load
232
+ expect(pwd).to receive(:warning).once
233
+ ps = pwd.get('this.is.a.host', 'user')
234
+ expect(ps).to eq('a test!')
235
+ end
236
+ end
237
+ end
238
+
239
+
240
+ end
241
+
242
+ # vim: set ai et sw=2 ts=2 :