vaulty 0.0.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 +7 -0
- data/.gitignore +8 -0
- data/.rspec +2 -0
- data/.rubocop.yml +42 -0
- data/.rubocop_todo.yml +11 -0
- data/.travis.yml +34 -0
- data/Gemfile +13 -0
- data/LICENSE +21 -0
- data/README.md +18 -0
- data/Rakefile +31 -0
- data/bin/vaulty +8 -0
- data/lib/vaulty/catacomb.rb +113 -0
- data/lib/vaulty/cli/add.rb +32 -0
- data/lib/vaulty/cli/command.rb +21 -0
- data/lib/vaulty/cli/delete.rb +36 -0
- data/lib/vaulty/cli/tree.rb +27 -0
- data/lib/vaulty/cli_app.rb +137 -0
- data/lib/vaulty/output/banner.rb +24 -0
- data/lib/vaulty/output/table.rb +44 -0
- data/lib/vaulty/output/tree.rb +47 -0
- data/lib/vaulty/vault_tree.rb +72 -0
- data/lib/vaulty/version.rb +3 -0
- data/lib/vaulty.rb +23 -0
- data/vaulty.gemspec +32 -0
- data/vaulty.rdoc +90 -0
- metadata +154 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: e424ce87a9674979f10dad0855b27a2fa76763c4
|
|
4
|
+
data.tar.gz: bd26c4d66ac5b7d1da3b85fac301a3c761342fe0
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ea10a384993cae89b6ef4bf52375aaf2038dd8f87640890f082767281a8583fa2e28dd4bef28ce0b323850bb56858a3cac05e4614b09d8b294fe3b422494899c
|
|
7
|
+
data.tar.gz: '0994e597a90351fc5a33059df95f30f2a1198c2b5597e8909415a64f45d5382637a33e257b679e3b92279ad831e9f721d61325c09a6e63010b9b689b058130b7'
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
|
2
|
+
|
|
3
|
+
AllCops:
|
|
4
|
+
TargetRubyVersion: 2.3
|
|
5
|
+
Exclude:
|
|
6
|
+
- 'bin/*'
|
|
7
|
+
- 'spec/**/*'
|
|
8
|
+
|
|
9
|
+
# Don't care about frozen strings
|
|
10
|
+
Style/FrozenStringLiteralComment:
|
|
11
|
+
Enabled: false
|
|
12
|
+
|
|
13
|
+
# Don't care about code comments (yet)
|
|
14
|
+
Style/Documentation:
|
|
15
|
+
Enabled: false
|
|
16
|
+
|
|
17
|
+
Metrics/LineLength:
|
|
18
|
+
Max: 90
|
|
19
|
+
|
|
20
|
+
Style/AlignHash:
|
|
21
|
+
EnforcedColonStyle: key
|
|
22
|
+
EnforcedHashRocketStyle: key
|
|
23
|
+
|
|
24
|
+
Style/AlignParameters:
|
|
25
|
+
Enabled: false
|
|
26
|
+
|
|
27
|
+
Style/IndentHash:
|
|
28
|
+
EnforcedStyle: consistent
|
|
29
|
+
|
|
30
|
+
# Only exclude the CLI app since we cannot split this up in the current form
|
|
31
|
+
Metrics/ClassLength:
|
|
32
|
+
Exclude:
|
|
33
|
+
- 'lib/vaulty/cli_app.rb'
|
|
34
|
+
|
|
35
|
+
Style/PercentLiteralDelimiters:
|
|
36
|
+
PreferredDelimiters:
|
|
37
|
+
default: ()
|
|
38
|
+
'%i': '()'
|
|
39
|
+
'%I': '()'
|
|
40
|
+
'%r': '{}'
|
|
41
|
+
'%w': '()'
|
|
42
|
+
'%W': '()'
|
data/.rubocop_todo.yml
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# This configuration was generated by
|
|
2
|
+
# `rubocop --auto-gen-config`
|
|
3
|
+
# on 2017-04-19 16:33:02 +0200 using RuboCop version 0.48.1.
|
|
4
|
+
# The point is for the user to remove these configuration records
|
|
5
|
+
# one by one as the offenses are removed from the code base.
|
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
|
8
|
+
|
|
9
|
+
# Offense count: 2
|
|
10
|
+
Metrics/AbcSize:
|
|
11
|
+
Max: 25
|
data/.travis.yml
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
dist: trusty
|
|
2
|
+
sudo: false
|
|
3
|
+
language: ruby
|
|
4
|
+
cache: bundler
|
|
5
|
+
|
|
6
|
+
before_install:
|
|
7
|
+
- curl -sLo vault.zip https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip
|
|
8
|
+
- unzip vault.zip
|
|
9
|
+
- mkdir ~/bin
|
|
10
|
+
- mv vault ~/bin
|
|
11
|
+
- export PATH="~/bin:$PATH"
|
|
12
|
+
- gem update --remote bundler
|
|
13
|
+
|
|
14
|
+
install:
|
|
15
|
+
- bundle install --retry=3
|
|
16
|
+
|
|
17
|
+
env:
|
|
18
|
+
- VAULT_VERSION=0.7.0
|
|
19
|
+
|
|
20
|
+
rvm:
|
|
21
|
+
- 2.3.1
|
|
22
|
+
- 2.4.1
|
|
23
|
+
|
|
24
|
+
script:
|
|
25
|
+
- 'bundle exec rake spec'
|
|
26
|
+
- 'bundle exec rubocop'
|
|
27
|
+
|
|
28
|
+
addons:
|
|
29
|
+
code_climate:
|
|
30
|
+
repo_token:
|
|
31
|
+
secure: "nof51qBnGYKwvJGsFrECGdnsttHoihTFKBOPlJV7M9qIO5WKGdg/hHFTA1oIaq8njlrGs166IA9gD8IUFpVaesSVMr9W9l7LdgbcMNf+hmTLA8MmrIjTJMsyBSSXK5H7nmd36VS+XzFjhviYeVgSVppZdv+Rxyo3neieq6R6u/Ik3VLTp7RjA38Yh45iiRd549OO+A0ufZ9oOySuA03WPAiPWhyjjScK2L8+HYH5G6pEhhm6+GfN6DZU6QWbNPBCGEDk5RnLb1SfoxYDNlXZlEMre+gzO+78bquZVQOqEGF7VJUD/kDW8ZO4abEvWeDL6tlEsU5EnDAu5EIwDSZFVQUSbsqoyyX8r64EHzomaF4QAIuRZ7/5N8hJ6h+qAlxOJ3NML1+tALQriY5e5vh7ler1IjC3tozfGouMIoKFTe6FVBZir799Dm5jjVfvTDoYoLj1QcsplFtZw0s6lUQc3fNMFNPmS9t/xIDqPGNJvd5jCKYkdXs1bld9XdvjklyZglNp+cU8RMzEr6R9XvQGvjZSZqyO8IOOXMwwJpTNJ6Swt+kmAmogG5s30STE296+4Sp8/u9xfRoYbwKLbj7LwMl7IVnfQLqCfdJxVfRlCw3mxPn1mECXys2C+GFjqh0u/wPci1qAqyBBKnG1kSScfBdvuQqIoAs6nfDZFShLxlg="
|
|
32
|
+
|
|
33
|
+
after_success:
|
|
34
|
+
- bundle exec codeclimate-test-reporter
|
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017 PlayPass
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Vaulty
|
|
2
|
+
[](https://travis-ci.org/playpasshq/vaulty)
|
|
3
|
+
[](https://coveralls.io/github/playpasshq/vaulty?branch=master)
|
|
4
|
+
[](https://codeclimate.com/github/playpasshq/vaulty)
|
|
5
|
+
[](https://codeclimate.com/github/playpasshq/vaulty)
|
|
6
|
+
[](https://gemnasium.com/github.com/playpasshq/vaulty)
|
|
7
|
+
[](http://inch-ci.org/github/playpasshq/vaulty)
|
|
8
|
+
[](https://git.legal/projects/3808)
|
|
9
|
+
|
|
10
|
+
Vaulty is a CLI application that makes it easier to manage Vault.
|
|
11
|
+
Only tested on the generic backend!
|
|
12
|
+
|
|
13
|
+
## Project Status
|
|
14
|
+
|
|
15
|
+
Very alpha, only 3 commands are supported.
|
|
16
|
+
|
|
17
|
+
:include:vaulty.rdoc
|
|
18
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rubygems/package_task'
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'bundler/gem_tasks'
|
|
5
|
+
|
|
6
|
+
begin
|
|
7
|
+
Bundler.setup(:default, :development)
|
|
8
|
+
rescue Bundler::BundlerError => e
|
|
9
|
+
$stderr.puts e.message
|
|
10
|
+
$stderr.puts 'Run `bundle install` to install missing gems'
|
|
11
|
+
exit e.status_code
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
require 'rake'
|
|
15
|
+
require 'rspec/core'
|
|
16
|
+
require 'rspec/core/rake_task'
|
|
17
|
+
require 'rubocop/rake_task'
|
|
18
|
+
|
|
19
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
20
|
+
RuboCop::RakeTask.new(:rubocop)
|
|
21
|
+
|
|
22
|
+
desc 'Run RSpec with code coverage'
|
|
23
|
+
task :coverage do
|
|
24
|
+
ENV['COVERAGE'] = 'true'
|
|
25
|
+
Rake::Task['spec'].execute
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
task default: %i(spec rubocop)
|
|
29
|
+
|
|
30
|
+
require 'yard'
|
|
31
|
+
YARD::Rake::YardocTask.new
|
data/bin/vaulty
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
module Vaulty
|
|
2
|
+
class Catacomb
|
|
3
|
+
attr_reader :path
|
|
4
|
+
# @param [String] the path to be used
|
|
5
|
+
def initialize(path)
|
|
6
|
+
@path = path
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Checks if the key is found in the data
|
|
10
|
+
# @param [String] key
|
|
11
|
+
# @return [Boolean]
|
|
12
|
+
#
|
|
13
|
+
def key?(key)
|
|
14
|
+
read.key?(key.to_sym)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Checks if any of the provided keys are found in the data
|
|
18
|
+
# @param [Array<String>] keys
|
|
19
|
+
# @return [Boolean]
|
|
20
|
+
#
|
|
21
|
+
def keys?(keys)
|
|
22
|
+
matching_keys(keys).any?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Returns matching keys
|
|
26
|
+
# @param [Array<String>] keys
|
|
27
|
+
# @return [Array<String>] keys that matched
|
|
28
|
+
#
|
|
29
|
+
def matching_keys(keys)
|
|
30
|
+
Array(keys).select { |key| key?(key) }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Writes data to Vault with an optional confirm/msg
|
|
34
|
+
# @param [Hash] data
|
|
35
|
+
#
|
|
36
|
+
def write(data)
|
|
37
|
+
self.class.write(path, data)
|
|
38
|
+
reload
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Merges the data to Vault with an optional confirm/msg
|
|
42
|
+
# @param [Hash] data
|
|
43
|
+
#
|
|
44
|
+
def merge(data)
|
|
45
|
+
current = read
|
|
46
|
+
write(current.merge(data))
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Reads the data from Vault, always returns an Hash
|
|
50
|
+
# @return [Hash]
|
|
51
|
+
#
|
|
52
|
+
def read
|
|
53
|
+
@read ||= self.class.read(path)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Clears the cached result from read and returns the result
|
|
57
|
+
# @return [Hash]
|
|
58
|
+
#
|
|
59
|
+
def reload
|
|
60
|
+
@read = nil
|
|
61
|
+
read
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Deletes a path (with all values) from Vault
|
|
65
|
+
# @param [Boolean] confirm
|
|
66
|
+
# @param [String] msg
|
|
67
|
+
# @return [True]
|
|
68
|
+
#
|
|
69
|
+
def delete
|
|
70
|
+
self.class.delete(path)
|
|
71
|
+
@read = nil
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
class << self
|
|
75
|
+
# Wrapper around Vault logical read, return always a hash
|
|
76
|
+
# @param [String] path
|
|
77
|
+
# @return [Hash]
|
|
78
|
+
#
|
|
79
|
+
def read(path)
|
|
80
|
+
secret = Vault.logical.read(path)
|
|
81
|
+
secret ? secret.data : {}
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Wrapper around Vault logical write
|
|
85
|
+
# @param [String] path
|
|
86
|
+
# @param [Hash] data
|
|
87
|
+
# @return [Hash] secret
|
|
88
|
+
#
|
|
89
|
+
def write(path, data)
|
|
90
|
+
secret = Vault.logical.write(path, data)
|
|
91
|
+
secret.is_a?(Vault::Secret) ? secret.data : {}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Wrapper around Vault logical list
|
|
95
|
+
# @param [String] path
|
|
96
|
+
# @return [Array] secrets
|
|
97
|
+
#
|
|
98
|
+
def list(path)
|
|
99
|
+
list = Vault.logical.list(path)
|
|
100
|
+
cleaned_list = Array(list).map { |folder| folder.delete('/') }
|
|
101
|
+
cleaned_list.reject(&:empty?).uniq
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Wrapper around Vault logical delete
|
|
105
|
+
# @param [String] path
|
|
106
|
+
# @return [Boolean]
|
|
107
|
+
#
|
|
108
|
+
def delete(path)
|
|
109
|
+
Vault.logical.delete(path)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Vaulty
|
|
2
|
+
module CLI
|
|
3
|
+
class Add < Command
|
|
4
|
+
attr_reader :catacomb, :data
|
|
5
|
+
# @param [Catacomb] catacomb instance
|
|
6
|
+
# @param [Hash] data
|
|
7
|
+
def initialize(catacomb:, data:)
|
|
8
|
+
@catacomb = catacomb
|
|
9
|
+
@data = data
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call
|
|
13
|
+
banner("Current value #{catacomb.path.inspect}")
|
|
14
|
+
# Print out the current state
|
|
15
|
+
table(catacomb.read, highlight: { matching: matching_keys, color: :red })
|
|
16
|
+
# If we have matching keys and we don't want to continue, we exit
|
|
17
|
+
return if matching_keys.any? && prompt.no?('Existing secret found, overwrite?')
|
|
18
|
+
# Print we are writing and merge the content
|
|
19
|
+
banner("Writing data to #{catacomb.path.inspect}", color: :red)
|
|
20
|
+
catacomb.merge(data)
|
|
21
|
+
# Print the final state in a table highlight the values we added
|
|
22
|
+
table(catacomb.read, highlight: { matching: data.values, color: :green })
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def matching_keys
|
|
28
|
+
@matching_keys ||= catacomb.matching_keys(data.keys)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Vaulty
|
|
2
|
+
module CLI
|
|
3
|
+
class Command
|
|
4
|
+
def banner(msg, color: :green)
|
|
5
|
+
Vaulty::Output::Banner.render(msg, color: color)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def table(data, highlight: {})
|
|
9
|
+
Vaulty::Output::Table.render(data, highlight: highlight)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def prompt
|
|
13
|
+
@prompt ||= TTY::Prompt.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.call(*args)
|
|
17
|
+
new(*args).call
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Vaulty
|
|
2
|
+
module CLI
|
|
3
|
+
class Delete < Command
|
|
4
|
+
attr_reader :catacomb
|
|
5
|
+
def initialize(catacomb:)
|
|
6
|
+
@catacomb = catacomb
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def call
|
|
10
|
+
banner("Current value #{catacomb.path.inspect}")
|
|
11
|
+
# Render the tree first so the user knows what we will delete
|
|
12
|
+
Vaulty::CLI::Tree.call(catacomb)
|
|
13
|
+
# Confirmation
|
|
14
|
+
return if prompt.no?('All above data will be ' \
|
|
15
|
+
'recursively deleted! Are you sure?', color: :red)
|
|
16
|
+
|
|
17
|
+
banner(catacomb.path, color: :red)
|
|
18
|
+
# Start deleting
|
|
19
|
+
delete_recursively(vaulty_tree.children, [catacomb.path])
|
|
20
|
+
# Delete the route of the path
|
|
21
|
+
catacomb.delete
|
|
22
|
+
prompt.ok("Successfully deleted everything in path #{catacomb.path}")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def delete_recursively(tree, path = [])
|
|
28
|
+
Array(tree).each do |folder|
|
|
29
|
+
current_path = path + [folder.name]
|
|
30
|
+
Catacomb.delete(current_path.join('/')) unless folder.data.empty?
|
|
31
|
+
delete_recursively(folder.children, current_path) unless folder.children.empty?
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Vaulty
|
|
2
|
+
module CLI
|
|
3
|
+
class Tree < Command
|
|
4
|
+
class Empty < GLI::CustomExit
|
|
5
|
+
def initialize(path)
|
|
6
|
+
super("Path #{path.inspect} contains nothing", -1)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
attr_reader :catacomb
|
|
11
|
+
# @param [Catacomb] catacomb instance
|
|
12
|
+
def initialize(catacomb:)
|
|
13
|
+
@catacomb = catacomb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def call
|
|
17
|
+
spinner = TTY::Spinner.new('Loading :spinner', format: :arrow_pulse, clear: true)
|
|
18
|
+
spinner.auto_spin
|
|
19
|
+
vaulty_tree = Vaulty::VaultTree.new(catacomb: catacomb).tree
|
|
20
|
+
spinner.stop
|
|
21
|
+
|
|
22
|
+
raise Empty, catacomb.path if vaulty_tree.empty?
|
|
23
|
+
Vaulty::Output::Tree.render(vaulty_tree)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
module Vaulty
|
|
2
|
+
class CLIApp
|
|
3
|
+
extend GLI::App
|
|
4
|
+
|
|
5
|
+
program_desc 'Describe your application here'
|
|
6
|
+
|
|
7
|
+
version Vaulty::VERSION
|
|
8
|
+
|
|
9
|
+
subcommand_option_handling :normal
|
|
10
|
+
arguments :strict
|
|
11
|
+
|
|
12
|
+
accept(Array) do |value|
|
|
13
|
+
Hash[*value.split(':')]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
desc 'Describe some switch here'
|
|
17
|
+
switch %i(s switch)
|
|
18
|
+
|
|
19
|
+
desc 'Describe some flag here'
|
|
20
|
+
default_value 'the default'
|
|
21
|
+
arg_name 'The name of the argument'
|
|
22
|
+
flag %i(f flagname)
|
|
23
|
+
|
|
24
|
+
desc 'Add a new key/value to the given `PATH`, multiple `key:value` can be provided'
|
|
25
|
+
arg(:path)
|
|
26
|
+
command :add do |c|
|
|
27
|
+
c.flag %i(secret s), desc: 'Key/Values to save', type: Array, multiple: true,
|
|
28
|
+
required: true, arg_name: 'key:secret'
|
|
29
|
+
|
|
30
|
+
c.action do |_global_options, options, _args|
|
|
31
|
+
data = options[:secret].reduce({}, :merge)
|
|
32
|
+
catacomb = options[:catacomb]
|
|
33
|
+
Vaulty::CLI::Add.call(catacomb: catacomb, data: data)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
desc 'Deletes everything under the path recursively'
|
|
38
|
+
arg(:path)
|
|
39
|
+
command :delete do |c|
|
|
40
|
+
c.action do |_global_options, options, _args|
|
|
41
|
+
catacomb = options[:catacomb]
|
|
42
|
+
Vaulty::CLI::Delete.call(catacomb: catacomb)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
desc 'Represents the path as a tree'
|
|
47
|
+
arg(:path)
|
|
48
|
+
command :tree do |c|
|
|
49
|
+
c.action do |_global_options, options, _args|
|
|
50
|
+
catacomb = options[:catacomb]
|
|
51
|
+
Vaulty::CLI::Tree.call(catacomb: catacomb)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
desc 'Describe backup here'
|
|
56
|
+
arg_name 'Describe arguments to backup here'
|
|
57
|
+
command :backup do |c|
|
|
58
|
+
c.action do |_global_options, _options, _args|
|
|
59
|
+
puts 'backup command ran'
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
desc 'Describe convert here'
|
|
64
|
+
arg_name 'Describe arguments to convert here'
|
|
65
|
+
command :convert do |c|
|
|
66
|
+
c.action do |_global_options, _options, _args|
|
|
67
|
+
puts 'convert command ran'
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
desc 'Describe diff here'
|
|
72
|
+
arg_name 'Describe arguments to diff here'
|
|
73
|
+
command :diff do |c|
|
|
74
|
+
c.action do |_global_options, _options, _args|
|
|
75
|
+
puts 'diff command ran'
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
desc 'Describe generate here'
|
|
80
|
+
arg_name 'Describe arguments to generate here'
|
|
81
|
+
command :generate do |c|
|
|
82
|
+
c.action do |_global_options, _options, _args|
|
|
83
|
+
puts 'generate command ran'
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
desc 'Describe provision here'
|
|
88
|
+
arg_name 'Describe arguments to provision here'
|
|
89
|
+
command :provision do |c|
|
|
90
|
+
c.action do |_global_options, _options, _args|
|
|
91
|
+
puts 'provision command ran'
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
desc 'Describe remove here'
|
|
96
|
+
arg_name 'Describe arguments to remove here'
|
|
97
|
+
command :remove do |c|
|
|
98
|
+
c.action do |_global_options, _options, _args|
|
|
99
|
+
puts 'remove command ran'
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
desc 'Describe restore here'
|
|
104
|
+
arg_name 'Describe arguments to restore here'
|
|
105
|
+
command :restore do |c|
|
|
106
|
+
c.action do |_global_options, _options, _args|
|
|
107
|
+
puts 'restore command ran'
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
desc 'Describe write here'
|
|
112
|
+
arg_name 'Describe arguments to write here'
|
|
113
|
+
command :write do |c|
|
|
114
|
+
c.action do |_global_options, _options, _args|
|
|
115
|
+
puts 'write command ran'
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
pre do |_global, _command, options, args|
|
|
120
|
+
path = args.first
|
|
121
|
+
exit_now!('path must be provided') if path.nil? || path.empty?
|
|
122
|
+
options[:catacomb] = Vaulty::Catacomb.new(path)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
post do |global, command, options, args|
|
|
126
|
+
# Post logic here
|
|
127
|
+
# Use skips_post before a command to skip this
|
|
128
|
+
# block on that command only
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
on_error do |_exception|
|
|
132
|
+
# Error logic here
|
|
133
|
+
# return false to skip default error handling
|
|
134
|
+
true
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Vaulty
|
|
2
|
+
module Output
|
|
3
|
+
class Banner
|
|
4
|
+
attr_reader :msg, :prompt, :color
|
|
5
|
+
|
|
6
|
+
def initialize(msg, color: :blue)
|
|
7
|
+
@msg = msg
|
|
8
|
+
@color = "on_#{color}".to_sym
|
|
9
|
+
@prompt = TTY::Prompt.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def render
|
|
13
|
+
now = Time.new.strftime('%H:%M:%S')
|
|
14
|
+
formatted = msg.ljust(72, ' ')
|
|
15
|
+
prompt.say("[#{now}] #{formatted}", color: %I(bold white #{color}))
|
|
16
|
+
puts
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.render(*args)
|
|
20
|
+
new(*args).render
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Vaulty
|
|
2
|
+
module Output
|
|
3
|
+
class HighlightFilter
|
|
4
|
+
attr_reader :matching, :color
|
|
5
|
+
def initialize(matching: [], color: :red)
|
|
6
|
+
@matching = matching
|
|
7
|
+
@color = color
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call(val, _row, _column)
|
|
11
|
+
matching.include?(val.strip) ? pastel.decorate(val, color) : val
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def pastel
|
|
15
|
+
Pastel::Color.new(enabled: true)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class Table
|
|
20
|
+
DEFAULT_HEADER = %w(Key Value).freeze
|
|
21
|
+
attr_reader :data, :prompt, :header
|
|
22
|
+
|
|
23
|
+
def initialize(data, header: DEFAULT_HEADER, highlight: {})
|
|
24
|
+
@data = data
|
|
25
|
+
@prompt = TTY::Prompt.new
|
|
26
|
+
@filter = HighlightFilter.new(**highlight)
|
|
27
|
+
@header = header
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def render
|
|
31
|
+
table = TTY::Table.new(data, header: header, style: :markdown)
|
|
32
|
+
renderer = table.render(:ascii) do |render|
|
|
33
|
+
render.padding = [0, 2, 0, 2]
|
|
34
|
+
render.filter = @filter
|
|
35
|
+
end
|
|
36
|
+
prompt.say renderer
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.render(*args)
|
|
40
|
+
new(*args).render
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Vaulty
|
|
2
|
+
module Output
|
|
3
|
+
class Tree
|
|
4
|
+
attr_reader :tree, :value_icon, :dir_icon
|
|
5
|
+
|
|
6
|
+
def initialize(tree, value_icon: "\u{1F511}", dir_icon: "\u{1F4C2}")
|
|
7
|
+
@tree = tree
|
|
8
|
+
@value_icon = value_icon
|
|
9
|
+
@dir_icon = dir_icon
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def render
|
|
13
|
+
output_tree = flatten_tree(Array(tree), 0)
|
|
14
|
+
puts Hirb::Helpers::Tree.render(output_tree,
|
|
15
|
+
type: :directory,
|
|
16
|
+
multi_line_nodes: true)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.render(*args)
|
|
20
|
+
new(*args).render
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def flatten_tree(subtree, level = 0)
|
|
26
|
+
subtree.map do |folder|
|
|
27
|
+
[
|
|
28
|
+
format_node(folder.name, level),
|
|
29
|
+
format_values(folder.data, level + 1),
|
|
30
|
+
flatten_tree(folder.children, level + 1)
|
|
31
|
+
]
|
|
32
|
+
end.flatten.compact
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def format_values(values, level)
|
|
36
|
+
Array(values).map do |value|
|
|
37
|
+
key_value = "#{value.key}:#{value.value}"
|
|
38
|
+
{ value: [value_icon, key_value].compact.join(' '), level: level }
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def format_node(value, level)
|
|
43
|
+
{ value: [dir_icon, value].compact.join(' '), level: level }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module Vaulty
|
|
2
|
+
class VaultTree
|
|
3
|
+
class Folder
|
|
4
|
+
attr_reader :name, :data, :children
|
|
5
|
+
def initialize(name:, data:, children:)
|
|
6
|
+
@name = name
|
|
7
|
+
@data = data
|
|
8
|
+
@children = children
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def empty?
|
|
12
|
+
data.empty? && children.empty?
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Value
|
|
17
|
+
attr_reader :key, :value
|
|
18
|
+
def initialize(key:, value:)
|
|
19
|
+
@key = key
|
|
20
|
+
@value = value
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
attr_reader :catacomb
|
|
25
|
+
def initialize(catacomb:)
|
|
26
|
+
@catacomb = catacomb
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def tree
|
|
30
|
+
@tree ||= Folder.new(
|
|
31
|
+
name: catacomb.path,
|
|
32
|
+
data: read_values_for(catacomb.path),
|
|
33
|
+
children: find_subtree(catacomb.path)
|
|
34
|
+
)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def flatten
|
|
38
|
+
flatten_tree(Array(render))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def flatten_tree(subtree)
|
|
44
|
+
subtree.map do |folder|
|
|
45
|
+
{
|
|
46
|
+
name: folder.name,
|
|
47
|
+
data: folder.data.map(&:to_h),
|
|
48
|
+
children: flatten_tree(folder.children)
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def find_subtree(base_path)
|
|
54
|
+
list = Catacomb.list(base_path)
|
|
55
|
+
list.map do |folder|
|
|
56
|
+
file_or_folder = [base_path, folder].join('/')
|
|
57
|
+
values = read_values_for(file_or_folder)
|
|
58
|
+
Folder.new(
|
|
59
|
+
name: folder,
|
|
60
|
+
data: values,
|
|
61
|
+
children: find_subtree(file_or_folder)
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def read_values_for(path)
|
|
67
|
+
Catacomb.read(path).map do |key, value|
|
|
68
|
+
Value.new(key: key, value: value)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
data/lib/vaulty.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'vaulty/version.rb'
|
|
2
|
+
|
|
3
|
+
# Add requires for other files you add to your project here, so
|
|
4
|
+
# you just need to require this one file in your bin file
|
|
5
|
+
|
|
6
|
+
require 'gli'
|
|
7
|
+
require 'vault'
|
|
8
|
+
require 'hirb'
|
|
9
|
+
require 'hashdiff'
|
|
10
|
+
require 'tty'
|
|
11
|
+
require 'tty-prompt'
|
|
12
|
+
|
|
13
|
+
require 'vaulty/cli_app'
|
|
14
|
+
require 'vaulty/catacomb'
|
|
15
|
+
require 'vaulty/vault_tree'
|
|
16
|
+
|
|
17
|
+
require 'vaulty/cli/command'
|
|
18
|
+
require 'vaulty/cli/add'
|
|
19
|
+
require 'vaulty/cli/tree'
|
|
20
|
+
|
|
21
|
+
require 'vaulty/output/banner'
|
|
22
|
+
require 'vaulty/output/table'
|
|
23
|
+
require 'vaulty/output/tree'
|
data/vaulty.gemspec
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Ensure we require the local version and not one we might have installed already
|
|
2
|
+
require File.join([File.dirname(__FILE__), 'lib', 'vaulty', 'version.rb'])
|
|
3
|
+
Gem::Specification.new do |s|
|
|
4
|
+
s.name = 'vaulty'
|
|
5
|
+
s.version = Vaulty::VERSION
|
|
6
|
+
s.author = ['Jan Stevens']
|
|
7
|
+
s.email = ['jan@playpass.be']
|
|
8
|
+
s.platform = Gem::Platform::RUBY
|
|
9
|
+
|
|
10
|
+
s.summary = 'A description of your project'
|
|
11
|
+
s.description = 'Vault CLI that is based on the Vault Ruby gem'
|
|
12
|
+
s.homepage = 'https://fritz.ninja'
|
|
13
|
+
s.license = 'MIT'
|
|
14
|
+
|
|
15
|
+
s.required_ruby_version = '~> 2.3'
|
|
16
|
+
|
|
17
|
+
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
|
19
|
+
end
|
|
20
|
+
s.bindir = 'bin'
|
|
21
|
+
s.require_paths << 'lib'
|
|
22
|
+
s.executables << 'vaulty'
|
|
23
|
+
|
|
24
|
+
s.add_dependency 'vault', '~> 0.9'
|
|
25
|
+
s.add_dependency 'hirb', '~> 0.7.3'
|
|
26
|
+
s.add_dependency 'tty', '~> 0.7.0'
|
|
27
|
+
s.add_dependency 'hashdiff', '~> 0.3.0'
|
|
28
|
+
|
|
29
|
+
s.add_development_dependency 'rake'
|
|
30
|
+
|
|
31
|
+
s.add_runtime_dependency 'gli', '2.16.0'
|
|
32
|
+
end
|
data/vaulty.rdoc
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
== vaulty - Describe your application here
|
|
2
|
+
|
|
3
|
+
v0.0.1
|
|
4
|
+
|
|
5
|
+
=== Global Options
|
|
6
|
+
=== -f|--flagname The name of the argument
|
|
7
|
+
|
|
8
|
+
Describe some flag here
|
|
9
|
+
|
|
10
|
+
[Default Value] the default
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
=== --help
|
|
14
|
+
Show this message
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
=== -s|--[no-]switch
|
|
19
|
+
Describe some switch here
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
=== --version
|
|
24
|
+
Display the program version
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
=== Commands
|
|
29
|
+
==== Command: <tt>add </tt>
|
|
30
|
+
Add a new key/value to the given `PATH`, multiple `key:value` can be provided
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
===== Options
|
|
34
|
+
===== --secret|-s key:secret
|
|
35
|
+
|
|
36
|
+
Key/Values to save
|
|
37
|
+
|
|
38
|
+
[Default Value] None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
==== Command: <tt>backup Describe arguments to backup here</tt>
|
|
42
|
+
Describe backup here
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
==== Command: <tt>convert Describe arguments to convert here</tt>
|
|
46
|
+
Describe convert here
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
==== Command: <tt>delete </tt>
|
|
50
|
+
Deletes everything under the path recursively
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
==== Command: <tt>diff Describe arguments to diff here</tt>
|
|
54
|
+
Describe diff here
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
==== Command: <tt>generate Describe arguments to generate here</tt>
|
|
58
|
+
Describe generate here
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
==== Command: <tt>help command</tt>
|
|
62
|
+
Shows a list of commands or help for one command
|
|
63
|
+
|
|
64
|
+
Gets help for the application or its commands. Can also list the commands in a way helpful to creating a bash-style completion function
|
|
65
|
+
===== Options
|
|
66
|
+
===== -c
|
|
67
|
+
List commands one per line, to assist with shell completion
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
==== Command: <tt>provision Describe arguments to provision here</tt>
|
|
72
|
+
Describe provision here
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
==== Command: <tt>remove Describe arguments to remove here</tt>
|
|
76
|
+
Describe remove here
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
==== Command: <tt>restore Describe arguments to restore here</tt>
|
|
80
|
+
Describe restore here
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
==== Command: <tt>tree </tt>
|
|
84
|
+
Represents the path as a tree
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
==== Command: <tt>write Describe arguments to write here</tt>
|
|
88
|
+
Describe write here
|
|
89
|
+
|
|
90
|
+
|
metadata
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: vaulty
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Jan Stevens
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2017-04-19 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: vault
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0.9'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0.9'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: hirb
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 0.7.3
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 0.7.3
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: tty
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: 0.7.0
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: 0.7.0
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: hashdiff
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 0.3.0
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 0.3.0
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rake
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: gli
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - '='
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: 2.16.0
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - '='
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: 2.16.0
|
|
97
|
+
description: Vault CLI that is based on the Vault Ruby gem
|
|
98
|
+
email:
|
|
99
|
+
- jan@playpass.be
|
|
100
|
+
executables:
|
|
101
|
+
- vaulty
|
|
102
|
+
extensions: []
|
|
103
|
+
extra_rdoc_files: []
|
|
104
|
+
files:
|
|
105
|
+
- ".gitignore"
|
|
106
|
+
- ".rspec"
|
|
107
|
+
- ".rubocop.yml"
|
|
108
|
+
- ".rubocop_todo.yml"
|
|
109
|
+
- ".travis.yml"
|
|
110
|
+
- Gemfile
|
|
111
|
+
- LICENSE
|
|
112
|
+
- README.md
|
|
113
|
+
- Rakefile
|
|
114
|
+
- bin/vaulty
|
|
115
|
+
- lib/vaulty.rb
|
|
116
|
+
- lib/vaulty/catacomb.rb
|
|
117
|
+
- lib/vaulty/cli/add.rb
|
|
118
|
+
- lib/vaulty/cli/command.rb
|
|
119
|
+
- lib/vaulty/cli/delete.rb
|
|
120
|
+
- lib/vaulty/cli/tree.rb
|
|
121
|
+
- lib/vaulty/cli_app.rb
|
|
122
|
+
- lib/vaulty/output/banner.rb
|
|
123
|
+
- lib/vaulty/output/table.rb
|
|
124
|
+
- lib/vaulty/output/tree.rb
|
|
125
|
+
- lib/vaulty/vault_tree.rb
|
|
126
|
+
- lib/vaulty/version.rb
|
|
127
|
+
- vaulty.gemspec
|
|
128
|
+
- vaulty.rdoc
|
|
129
|
+
homepage: https://fritz.ninja
|
|
130
|
+
licenses:
|
|
131
|
+
- MIT
|
|
132
|
+
metadata: {}
|
|
133
|
+
post_install_message:
|
|
134
|
+
rdoc_options: []
|
|
135
|
+
require_paths:
|
|
136
|
+
- lib
|
|
137
|
+
- lib
|
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
139
|
+
requirements:
|
|
140
|
+
- - "~>"
|
|
141
|
+
- !ruby/object:Gem::Version
|
|
142
|
+
version: '2.3'
|
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
|
+
requirements:
|
|
145
|
+
- - ">="
|
|
146
|
+
- !ruby/object:Gem::Version
|
|
147
|
+
version: '0'
|
|
148
|
+
requirements: []
|
|
149
|
+
rubyforge_project:
|
|
150
|
+
rubygems_version: 2.6.11
|
|
151
|
+
signing_key:
|
|
152
|
+
specification_version: 4
|
|
153
|
+
summary: A description of your project
|
|
154
|
+
test_files: []
|