MuranoCLI 2.0.0
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 +7 -0
- data/.gitignore +28 -0
- data/.rspec +2 -0
- data/.travis.yml +21 -0
- data/Gemfile +27 -0
- data/LICENSE.txt +19 -0
- data/MuranoCLI.gemspec +50 -0
- data/MuranoCLI.iss +50 -0
- data/README.markdown +208 -0
- data/Rakefile +188 -0
- data/TODO.taskpaper +122 -0
- data/bin/mr +8 -0
- data/bin/murano +84 -0
- data/docs/demo.md +109 -0
- data/lib/MrMurano/Account.rb +211 -0
- data/lib/MrMurano/Config-Migrate.rb +47 -0
- data/lib/MrMurano/Config.rb +286 -0
- data/lib/MrMurano/Mock.rb +63 -0
- data/lib/MrMurano/Product-1P-Device.rb +145 -0
- data/lib/MrMurano/Product-Resources.rb +195 -0
- data/lib/MrMurano/Product.rb +358 -0
- data/lib/MrMurano/ProjectFile.rb +349 -0
- data/lib/MrMurano/Solution-Cors.rb +46 -0
- data/lib/MrMurano/Solution-Endpoint.rb +177 -0
- data/lib/MrMurano/Solution-File.rb +150 -0
- data/lib/MrMurano/Solution-ServiceConfig.rb +140 -0
- data/lib/MrMurano/Solution-Services.rb +326 -0
- data/lib/MrMurano/Solution-Users.rb +129 -0
- data/lib/MrMurano/Solution.rb +59 -0
- data/lib/MrMurano/SubCmdGroupContext.rb +49 -0
- data/lib/MrMurano/SyncUpDown.rb +565 -0
- data/lib/MrMurano/commands/assign.rb +57 -0
- data/lib/MrMurano/commands/businessList.rb +45 -0
- data/lib/MrMurano/commands/completion.rb +152 -0
- data/lib/MrMurano/commands/config.rb +67 -0
- data/lib/MrMurano/commands/content.rb +130 -0
- data/lib/MrMurano/commands/cors.rb +30 -0
- data/lib/MrMurano/commands/domain.rb +17 -0
- data/lib/MrMurano/commands/gb.rb +33 -0
- data/lib/MrMurano/commands/init.rb +138 -0
- data/lib/MrMurano/commands/keystore.rb +157 -0
- data/lib/MrMurano/commands/logs.rb +78 -0
- data/lib/MrMurano/commands/mock.rb +63 -0
- data/lib/MrMurano/commands/password.rb +88 -0
- data/lib/MrMurano/commands/postgresql.rb +41 -0
- data/lib/MrMurano/commands/product.rb +14 -0
- data/lib/MrMurano/commands/productCreate.rb +39 -0
- data/lib/MrMurano/commands/productDelete.rb +33 -0
- data/lib/MrMurano/commands/productDevice.rb +84 -0
- data/lib/MrMurano/commands/productDeviceIdCmds.rb +86 -0
- data/lib/MrMurano/commands/productList.rb +45 -0
- data/lib/MrMurano/commands/productWrite.rb +27 -0
- data/lib/MrMurano/commands/show.rb +80 -0
- data/lib/MrMurano/commands/solution.rb +14 -0
- data/lib/MrMurano/commands/solutionCreate.rb +39 -0
- data/lib/MrMurano/commands/solutionDelete.rb +34 -0
- data/lib/MrMurano/commands/solutionList.rb +45 -0
- data/lib/MrMurano/commands/status.rb +92 -0
- data/lib/MrMurano/commands/sync.rb +60 -0
- data/lib/MrMurano/commands/timeseries.rb +115 -0
- data/lib/MrMurano/commands/tsdb.rb +271 -0
- data/lib/MrMurano/commands/usage.rb +23 -0
- data/lib/MrMurano/commands/zshcomplete.erb +112 -0
- data/lib/MrMurano/commands.rb +32 -0
- data/lib/MrMurano/hash.rb +20 -0
- data/lib/MrMurano/http.rb +153 -0
- data/lib/MrMurano/makePretty.rb +75 -0
- data/lib/MrMurano/schema/pf-v1.0.0.yaml +114 -0
- data/lib/MrMurano/schema/sf-v0.2.0.yaml +77 -0
- data/lib/MrMurano/schema/sf-v0.3.0.yaml +78 -0
- data/lib/MrMurano/template/mock.erb +9 -0
- data/lib/MrMurano/template/projectFile.murano.erb +81 -0
- data/lib/MrMurano/verbosing.rb +99 -0
- data/lib/MrMurano/version.rb +4 -0
- data/lib/MrMurano.rb +20 -0
- data/spec/Account-Passwords_spec.rb +242 -0
- data/spec/Account_spec.rb +272 -0
- data/spec/ConfigFile_spec.rb +50 -0
- data/spec/ConfigMigrate_spec.rb +89 -0
- data/spec/Config_spec.rb +409 -0
- data/spec/Http_spec.rb +204 -0
- data/spec/MakePretties_spec.rb +118 -0
- data/spec/Mock_spec.rb +53 -0
- data/spec/ProductBase_spec.rb +113 -0
- data/spec/ProductContent_spec.rb +162 -0
- data/spec/ProductResources_spec.rb +329 -0
- data/spec/Product_1P_Device_spec.rb +202 -0
- data/spec/Product_1P_RPC_spec.rb +175 -0
- data/spec/Product_spec.rb +153 -0
- data/spec/ProjectFile_spec.rb +324 -0
- data/spec/Solution-Cors_spec.rb +164 -0
- data/spec/Solution-Endpoint_spec.rb +581 -0
- data/spec/Solution-File_spec.rb +212 -0
- data/spec/Solution-ServiceConfig_spec.rb +202 -0
- data/spec/Solution-ServiceDevice_spec.rb +176 -0
- data/spec/Solution-ServiceEventHandler_spec.rb +385 -0
- data/spec/Solution-ServiceModules_spec.rb +465 -0
- data/spec/Solution-UsersRoles_spec.rb +207 -0
- data/spec/Solution_spec.rb +92 -0
- data/spec/SyncRoot_spec.rb +83 -0
- data/spec/SyncUpDown_spec.rb +495 -0
- data/spec/Verbosing_spec.rb +279 -0
- data/spec/_workspace.rb +27 -0
- data/spec/cmd_assign_spec.rb +51 -0
- data/spec/cmd_business_spec.rb +59 -0
- data/spec/cmd_common.rb +72 -0
- data/spec/cmd_config_spec.rb +68 -0
- data/spec/cmd_content_spec.rb +71 -0
- data/spec/cmd_cors_spec.rb +50 -0
- data/spec/cmd_device_spec.rb +96 -0
- data/spec/cmd_domain_spec.rb +32 -0
- data/spec/cmd_init_spec.rb +30 -0
- data/spec/cmd_keystore_spec.rb +97 -0
- data/spec/cmd_password_spec.rb +62 -0
- data/spec/cmd_status_spec.rb +239 -0
- data/spec/cmd_syncdown_spec.rb +86 -0
- data/spec/cmd_syncup_spec.rb +62 -0
- data/spec/cmd_usage_spec.rb +36 -0
- data/spec/fixtures/.mrmuranorc +9 -0
- data/spec/fixtures/ProjectFiles/invalid.yaml +9 -0
- data/spec/fixtures/ProjectFiles/only_meta.yaml +24 -0
- data/spec/fixtures/ProjectFiles/with_routes.yaml +27 -0
- data/spec/fixtures/SolutionFiles/0.2.0.json +20 -0
- data/spec/fixtures/SolutionFiles/0.2.0_invalid.json +18 -0
- data/spec/fixtures/SolutionFiles/0.2.json +21 -0
- data/spec/fixtures/SolutionFiles/0.3.0.json +20 -0
- data/spec/fixtures/SolutionFiles/0.3.0_invalid.json +19 -0
- data/spec/fixtures/SolutionFiles/0.3.json +20 -0
- data/spec/fixtures/SolutionFiles/basic.json +20 -0
- data/spec/fixtures/SolutionFiles/secret.json +6 -0
- data/spec/fixtures/configfile +9 -0
- data/spec/fixtures/dumped_config +42 -0
- data/spec/fixtures/mrmuranorc_deleted_bob +8 -0
- data/spec/fixtures/mrmuranorc_tool_bob +3 -0
- data/spec/fixtures/product_spec_files/example.exoline.spec.yaml +116 -0
- data/spec/fixtures/product_spec_files/example.murano.spec.yaml +14 -0
- data/spec/fixtures/product_spec_files/gwe.exoline.spec.yaml +21 -0
- data/spec/fixtures/product_spec_files/gwe.murano.spec.yaml +16 -0
- data/spec/fixtures/product_spec_files/lightbulb-no-state.yaml +11 -0
- data/spec/fixtures/product_spec_files/lightbulb.yaml +14 -0
- data/spec/fixtures/roles-three.yaml +11 -0
- data/spec/fixtures/syncable_content/assets/icon.png +0 -0
- data/spec/fixtures/syncable_content/assets/index.html +0 -0
- data/spec/fixtures/syncable_content/assets/js/script.js +0 -0
- data/spec/fixtures/syncable_content/modules/table_util.lua +58 -0
- data/spec/fixtures/syncable_content/routes/manyRoutes.lua +11 -0
- data/spec/fixtures/syncable_content/routes/singleRoute.lua +5 -0
- data/spec/fixtures/syncable_content/services/devdata.lua +18 -0
- data/spec/fixtures/syncable_content/services/timers.lua +4 -0
- data/spec/spec_helper.rb +119 -0
- 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 :
|
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 :
|