clarenceb-hiera-eyaml 2.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.
- data/.gitignore +8 -0
- data/.travis.yml +10 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +52 -0
- data/LICENSE.txt +21 -0
- data/PLUGINS.md +4 -0
- data/README.md +322 -0
- data/Rakefile +1 -0
- data/bin/eyaml +13 -0
- data/hiera-eyaml.gemspec +22 -0
- data/lib/hiera/backend/eyaml/CLI.rb +60 -0
- data/lib/hiera/backend/eyaml/commands.rb +21 -0
- data/lib/hiera/backend/eyaml/encryptor.rb +79 -0
- data/lib/hiera/backend/eyaml/encryptors/pkcs7.rb +107 -0
- data/lib/hiera/backend/eyaml/options.rb +35 -0
- data/lib/hiera/backend/eyaml/parser/encrypted_tokens.rb +138 -0
- data/lib/hiera/backend/eyaml/parser/parser.rb +82 -0
- data/lib/hiera/backend/eyaml/parser/token.rb +49 -0
- data/lib/hiera/backend/eyaml/plugins.rb +70 -0
- data/lib/hiera/backend/eyaml/subcommand.rb +126 -0
- data/lib/hiera/backend/eyaml/subcommands/createkeys.rb +29 -0
- data/lib/hiera/backend/eyaml/subcommands/decrypt.rb +81 -0
- data/lib/hiera/backend/eyaml/subcommands/edit.rb +105 -0
- data/lib/hiera/backend/eyaml/subcommands/encrypt.rb +100 -0
- data/lib/hiera/backend/eyaml/subcommands/help.rb +51 -0
- data/lib/hiera/backend/eyaml/subcommands/recrypt.rb +56 -0
- data/lib/hiera/backend/eyaml/subcommands/unknown_command.rb +48 -0
- data/lib/hiera/backend/eyaml/subcommands/version.rb +47 -0
- data/lib/hiera/backend/eyaml/utils.rb +172 -0
- data/lib/hiera/backend/eyaml.rb +48 -0
- data/lib/hiera/backend/eyaml_backend.rb +125 -0
- data/sublime_text/README.md +16 -0
- data/sublime_text/eyaml.sublime-package +0 -0
- data/sublime_text/eyaml.syntax_definition.json +288 -0
- data/tools/regem.sh +9 -0
- metadata +114 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'hiera/backend/eyaml'
|
2
|
+
require 'hiera/backend/eyaml/utils'
|
3
|
+
require 'hiera/backend/eyaml/options'
|
4
|
+
require 'hiera/backend/eyaml/parser/parser'
|
5
|
+
require 'hiera/backend/eyaml/subcommand'
|
6
|
+
|
7
|
+
class Hiera
|
8
|
+
module Backend
|
9
|
+
module Eyaml
|
10
|
+
module Subcommands
|
11
|
+
|
12
|
+
class Decrypt < Subcommand
|
13
|
+
|
14
|
+
def self.options
|
15
|
+
[{:name => :string,
|
16
|
+
:description => "Source input is a string provided as an argument",
|
17
|
+
:short => 's',
|
18
|
+
:type => :string},
|
19
|
+
{:name => :file,
|
20
|
+
:description => "Source input is a regular file",
|
21
|
+
:short => 'f',
|
22
|
+
:type => :string},
|
23
|
+
{:name => :eyaml,
|
24
|
+
:description => "Source input is an eyaml file",
|
25
|
+
:short => 'e',
|
26
|
+
:type => :string},
|
27
|
+
{:name => :stdin,
|
28
|
+
:description => "Source input is taken from stdin",
|
29
|
+
:short => :none}
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.description
|
34
|
+
"decrypt some data"
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.validate options
|
38
|
+
sources = [:eyaml, :password, :string, :file, :stdin].collect {|x| x if options[x]}.compact
|
39
|
+
Trollop::die "You must specify a source" if sources.count.zero?
|
40
|
+
Trollop::die "You can only specify one of (#{sources.join(', ')})" if sources.count > 1
|
41
|
+
options[:source] = sources.first
|
42
|
+
|
43
|
+
options[:input_data] = case options[:source]
|
44
|
+
when :stdin
|
45
|
+
STDIN.read
|
46
|
+
when :string
|
47
|
+
options[:string]
|
48
|
+
when :file
|
49
|
+
File.read options[:file]
|
50
|
+
when :eyaml
|
51
|
+
File.read options[:eyaml]
|
52
|
+
end
|
53
|
+
options
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.execute
|
57
|
+
parser = Parser::ParserFactory.encrypted_parser
|
58
|
+
tokens = parser.parse(Eyaml::Options[:input_data])
|
59
|
+
case Eyaml::Options[:source]
|
60
|
+
when :eyaml
|
61
|
+
decrypted = tokens.map{ |token| token.to_decrypted }
|
62
|
+
decrypted.join
|
63
|
+
else
|
64
|
+
decrypted = tokens.map{ |token|
|
65
|
+
case token.class.name
|
66
|
+
when /::EncToken$/
|
67
|
+
token.plain_text
|
68
|
+
else
|
69
|
+
token.match
|
70
|
+
end
|
71
|
+
}
|
72
|
+
decrypted.join
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'hiera/backend/eyaml/utils'
|
2
|
+
require 'hiera/backend/eyaml/options'
|
3
|
+
require 'hiera/backend/eyaml/parser/parser'
|
4
|
+
require 'hiera/backend/eyaml/subcommand'
|
5
|
+
require 'highline/import'
|
6
|
+
|
7
|
+
class Hiera
|
8
|
+
module Backend
|
9
|
+
module Eyaml
|
10
|
+
module Subcommands
|
11
|
+
|
12
|
+
class Edit < Subcommand
|
13
|
+
|
14
|
+
def self.options
|
15
|
+
[]
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.description
|
19
|
+
"edit an eyaml file"
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.helptext
|
23
|
+
"Usage: eyaml edit [options] <some-eyaml-file>"
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.validate options
|
27
|
+
Trollop::die "You must specify an eyaml file" if ARGV.empty?
|
28
|
+
options[:source] = :eyaml
|
29
|
+
options[:eyaml] = ARGV.shift
|
30
|
+
options[:input_data] = File.read options[:eyaml]
|
31
|
+
options
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.execute
|
35
|
+
encrypted_parser = Parser::ParserFactory.encrypted_parser
|
36
|
+
tokens = encrypted_parser.parse Eyaml::Options[:input_data]
|
37
|
+
decrypted_input = tokens.each_with_index.to_a.map{|(t,index)| t.to_decrypted :index => index}.join
|
38
|
+
decrypted_file = Utils.write_tempfile decrypted_input
|
39
|
+
|
40
|
+
editor = Utils.find_editor
|
41
|
+
|
42
|
+
begin
|
43
|
+
system "#{editor} #{decrypted_file}"
|
44
|
+
status = $?
|
45
|
+
|
46
|
+
raise StandardError, "File was moved by editor" unless File.file? decrypted_file
|
47
|
+
edited_file = File.read decrypted_file
|
48
|
+
|
49
|
+
raise StandardError, "Editor #{editor} has not exited?" unless status.exited?
|
50
|
+
raise StandardError, "Editor did not exit successfully (exit code #{status.exitstatus}), aborting" unless status.exitstatus == 0
|
51
|
+
raise StandardError, "Edited file is blank" if edited_file.empty?
|
52
|
+
|
53
|
+
if edited_file == decrypted_input
|
54
|
+
Utils.info "No changes detected, exiting"
|
55
|
+
else
|
56
|
+
decrypted_parser = Parser::ParserFactory.decrypted_parser
|
57
|
+
edited_tokens = decrypted_parser.parse(edited_file)
|
58
|
+
|
59
|
+
# check that the tokens haven't been copy / pasted
|
60
|
+
used_ids = edited_tokens.find_all{ |t| t.class.name =~ /::EncToken$/ and !t.id.nil? }.map{ |t| t.id }
|
61
|
+
if used_ids.length != used_ids.uniq.length
|
62
|
+
raise RecoverableError, "A duplicate DEC(ID) was found so I don't know how to proceed. This is probably because you copy and pasted a value - if you do this please delete the ID in parentheses"
|
63
|
+
end
|
64
|
+
|
65
|
+
# replace untouched values with the source values
|
66
|
+
edited_denoised_tokens = edited_tokens.map{ |token|
|
67
|
+
if token.class.name =~ /::EncToken$/ && !token.id.nil?
|
68
|
+
old_token = tokens[token.id]
|
69
|
+
if old_token.plain_text.eql? token.plain_text
|
70
|
+
old_token
|
71
|
+
else
|
72
|
+
token
|
73
|
+
end
|
74
|
+
else
|
75
|
+
token
|
76
|
+
end
|
77
|
+
}
|
78
|
+
|
79
|
+
encrypted_output = edited_denoised_tokens.map{ |t| t.to_encrypted }.join
|
80
|
+
|
81
|
+
filename = Eyaml::Options[:eyaml]
|
82
|
+
File.open("#{filename}", 'w') { |file|
|
83
|
+
file.write encrypted_output
|
84
|
+
}
|
85
|
+
end
|
86
|
+
rescue RecoverableError => e
|
87
|
+
Utils.info e
|
88
|
+
if agree "Return to the editor to try again?"
|
89
|
+
retry
|
90
|
+
else
|
91
|
+
raise e
|
92
|
+
end
|
93
|
+
ensure
|
94
|
+
Utils.secure_file_delete :file => decrypted_file, :num_bytes => [edited_file.length, decrypted_input.length].max
|
95
|
+
end
|
96
|
+
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'hiera/backend/eyaml/options'
|
2
|
+
require 'hiera/backend/eyaml/parser/parser'
|
3
|
+
require 'hiera/backend/eyaml/parser/encrypted_tokens'
|
4
|
+
require 'hiera/backend/eyaml/subcommand'
|
5
|
+
|
6
|
+
class Hiera
|
7
|
+
module Backend
|
8
|
+
module Eyaml
|
9
|
+
module Subcommands
|
10
|
+
|
11
|
+
class Encrypt < Subcommand
|
12
|
+
|
13
|
+
def self.options
|
14
|
+
[{:name => :password,
|
15
|
+
:description => "Source input is a password entered on the terminal",
|
16
|
+
:short => 'p'},
|
17
|
+
{:name => :string,
|
18
|
+
:description => "Source input is a string provided as an argument",
|
19
|
+
:short => 's',
|
20
|
+
:type => :string},
|
21
|
+
{:name => :file,
|
22
|
+
:description => "Source input is a regular file",
|
23
|
+
:short => 'f',
|
24
|
+
:type => :string},
|
25
|
+
{:name => :stdin,
|
26
|
+
:description => "Source input is taken from stdin",
|
27
|
+
:short => :none},
|
28
|
+
{:name => :eyaml,
|
29
|
+
:description => "Source input is an eyaml file",
|
30
|
+
:short => 'e',
|
31
|
+
:type => :string},
|
32
|
+
{:name => :output,
|
33
|
+
:description => "Output format of final result (examples, block, string)",
|
34
|
+
:type => :string,
|
35
|
+
:short => 'o',
|
36
|
+
:default => "examples"},
|
37
|
+
{:name => :label,
|
38
|
+
:description => "Apply a label to the encrypted result",
|
39
|
+
:short => 'l',
|
40
|
+
:type => :string}
|
41
|
+
]
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.description
|
45
|
+
"encrypt some data"
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.validate options
|
49
|
+
sources = [:password, :string, :file, :stdin, :eyaml].collect {|x| x if options[x]}.compact
|
50
|
+
Trollop::die "You must specify a source" if sources.count.zero?
|
51
|
+
Trollop::die "You can only specify one of (#{sources.join(', ')})" if sources.count > 1
|
52
|
+
options[:source] = sources.first
|
53
|
+
|
54
|
+
options[:input_data] = case options[:source]
|
55
|
+
when :password
|
56
|
+
Utils.read_password
|
57
|
+
when :string
|
58
|
+
options[:string]
|
59
|
+
when :file
|
60
|
+
File.read options[:file]
|
61
|
+
when :stdin
|
62
|
+
STDIN.read
|
63
|
+
when :eyaml
|
64
|
+
File.read options[:eyaml]
|
65
|
+
end
|
66
|
+
options
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.execute
|
71
|
+
case Eyaml::Options[:source]
|
72
|
+
when :eyaml
|
73
|
+
parser = Parser::ParserFactory.decrypted_parser
|
74
|
+
tokens = parser.parse(Eyaml::Options[:input_data])
|
75
|
+
encrypted = tokens.map{ |token| token.to_encrypted }
|
76
|
+
encrypted.join
|
77
|
+
else
|
78
|
+
encryptor = Encryptor.find
|
79
|
+
ciphertext = encryptor.encode( encryptor.encrypt(Eyaml::Options[:input_data]) )
|
80
|
+
token = Parser::EncToken.new(:block, Eyaml::Options[:input_data], encryptor, ciphertext, nil, ' ')
|
81
|
+
case Eyaml::Options[:output]
|
82
|
+
when "block"
|
83
|
+
token.to_encrypted :label => Eyaml::Options[:label], :use_chevron => !Eyaml::Options[:label].nil?, :format => :block
|
84
|
+
when "string"
|
85
|
+
token.to_encrypted :label => Eyaml::Options[:label], :format => :string
|
86
|
+
when "examples"
|
87
|
+
string = token.to_encrypted :label => Eyaml::Options[:label] || 'string', :format => :string
|
88
|
+
block = token.to_encrypted :label => Eyaml::Options[:label] || 'block', :format => :block
|
89
|
+
"#{string}\n\nOR\n\n#{block}"
|
90
|
+
else
|
91
|
+
token.to_encrypted :format => :string
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'hiera/backend/eyaml/subcommand'
|
2
|
+
require 'hiera/backend/eyaml'
|
3
|
+
|
4
|
+
class Hiera
|
5
|
+
module Backend
|
6
|
+
module Eyaml
|
7
|
+
module Subcommands
|
8
|
+
|
9
|
+
class Help < Subcommand
|
10
|
+
|
11
|
+
def self.options
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.description
|
16
|
+
"this page"
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.execute
|
20
|
+
|
21
|
+
puts <<-EOS
|
22
|
+
Welcome to eyaml #{Eyaml::VERSION}
|
23
|
+
|
24
|
+
Usage:
|
25
|
+
eyaml subcommand [global-opts] [subcommand-opts]
|
26
|
+
|
27
|
+
Available subcommands:
|
28
|
+
#{Eyaml.subcommands.collect {|command|
|
29
|
+
command_class = Subcommands.const_get(Utils.camelcase command)
|
30
|
+
sprintf "%15s: %-65s", command.downcase, command_class.description unless command_class.hidden?
|
31
|
+
}.compact.join("\n")}
|
32
|
+
|
33
|
+
For more help on an individual command, use --help on that command
|
34
|
+
|
35
|
+
Installed Plugins:
|
36
|
+
#{Plugins.plugins.collect {|plugin|
|
37
|
+
"\t" + plugin.name.split("hiera-eyaml-").last
|
38
|
+
}.join("\n")}
|
39
|
+
EOS
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.hidden?
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'hiera/backend/eyaml/subcommand'
|
2
|
+
require 'hiera/backend/eyaml/options'
|
3
|
+
require 'hiera/backend/eyaml/parser/parser'
|
4
|
+
|
5
|
+
class Hiera
|
6
|
+
module Backend
|
7
|
+
module Eyaml
|
8
|
+
module Subcommands
|
9
|
+
|
10
|
+
class Recrypt < Subcommand
|
11
|
+
|
12
|
+
def self.options
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.description
|
17
|
+
"recrypt an eyaml file"
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.helptext
|
21
|
+
"Usage: eyaml recrypt [options] <some-eyaml-file>"
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.validate options
|
25
|
+
Trollop::die "You must specify an eyaml file" if ARGV.empty?
|
26
|
+
options[:source] = :eyaml
|
27
|
+
options[:eyaml] = ARGV.shift
|
28
|
+
options[:input_data] = File.read options[:eyaml]
|
29
|
+
options
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.execute
|
33
|
+
|
34
|
+
encrypted_parser = Parser::ParserFactory.encrypted_parser
|
35
|
+
tokens = encrypted_parser.parse Eyaml::Options[:input_data]
|
36
|
+
decrypted_input = tokens.each_with_index.to_a.map{|(t,index)| t.to_decrypted :index => index}.join
|
37
|
+
|
38
|
+
decrypted_parser = Parser::ParserFactory.decrypted_parser
|
39
|
+
edited_tokens = decrypted_parser.parse(decrypted_input)
|
40
|
+
|
41
|
+
encrypted_output = edited_tokens.map{ |t| t.to_encrypted }.join
|
42
|
+
|
43
|
+
filename = Eyaml::Options[:eyaml]
|
44
|
+
File.open("#{filename}", 'w') { |file|
|
45
|
+
file.write encrypted_output
|
46
|
+
}
|
47
|
+
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'hiera/backend/eyaml/subcommand'
|
2
|
+
|
3
|
+
class Hiera
|
4
|
+
module Backend
|
5
|
+
module Eyaml
|
6
|
+
module Subcommands
|
7
|
+
|
8
|
+
class UnknownCommand < Eyaml::Subcommand
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_accessor :original_command
|
12
|
+
end
|
13
|
+
|
14
|
+
@@original_command = "unknown"
|
15
|
+
|
16
|
+
def self.options
|
17
|
+
[]
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.description
|
21
|
+
"Unknown command (#{@@original_command})"
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.execute
|
25
|
+
subcommands = Eyaml.subcommands
|
26
|
+
puts <<-EOS
|
27
|
+
Unknown subcommand#{ ": " + Eyaml.subcommand if Eyaml.subcommand }
|
28
|
+
|
29
|
+
Usage: eyaml <subcommand>
|
30
|
+
|
31
|
+
Please use one of the following subcommands or help for more help:
|
32
|
+
#{Eyaml.subcommands.sort.collect {|command|
|
33
|
+
command_class = Subcommands.const_get(Utils.camelcase command)
|
34
|
+
command unless command_class.hidden?
|
35
|
+
}.compact.join(", ")}
|
36
|
+
EOS
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.hidden?
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'hiera/backend/eyaml/subcommand'
|
2
|
+
require 'hiera/backend/eyaml'
|
3
|
+
|
4
|
+
class Hiera
|
5
|
+
module Backend
|
6
|
+
module Eyaml
|
7
|
+
module Subcommands
|
8
|
+
|
9
|
+
class Version < Subcommand
|
10
|
+
|
11
|
+
def self.options
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.description
|
16
|
+
"show version information"
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.execute
|
20
|
+
plugin_versions = {}
|
21
|
+
|
22
|
+
puts <<-EOS
|
23
|
+
Version info
|
24
|
+
|
25
|
+
hiera-eyaml (core): #{Eyaml::VERSION}
|
26
|
+
EOS
|
27
|
+
|
28
|
+
Plugins.plugins.each do |plugin|
|
29
|
+
plugin_shortname = plugin.name.split("hiera-eyaml-").last
|
30
|
+
plugin_version = begin
|
31
|
+
Encryptor.find(plugin_shortname)::VERSION.to_s
|
32
|
+
rescue
|
33
|
+
"unknown (is plugin compatible with eyaml 2.0+ ?)"
|
34
|
+
end
|
35
|
+
puts " hiera-eyaml-#{plugin_shortname} (gem): #{plugin_version}"
|
36
|
+
end
|
37
|
+
|
38
|
+
nil
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'highline/import'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class Hiera
|
6
|
+
module Backend
|
7
|
+
module Eyaml
|
8
|
+
class Utils
|
9
|
+
|
10
|
+
def self.read_password
|
11
|
+
ask("Enter password: ") {|q| q.echo = "*" }
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.confirm? message
|
15
|
+
result = ask("#{message} (y/N): ")
|
16
|
+
if result.downcase == "y" or result.downcase == "yes"
|
17
|
+
true
|
18
|
+
else
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.camelcase string
|
24
|
+
return string if string !~ /_/ && string =~ /[A-Z]+.*/
|
25
|
+
string.split('_').map{|e| e.capitalize}.join
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.snakecase string
|
29
|
+
return string if string !~ /[A-Z]/
|
30
|
+
string.split(/(?=[A-Z])/).collect {|x| x.downcase}.join("_")
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.find_editor
|
34
|
+
editor = ENV['EDITOR']
|
35
|
+
editor ||= %w{ /usr/bin/sensible-editor /usr/bin/editor /usr/bin/vim /usr/bin/vi }.collect {|e| e if FileTest.executable? e}.compact.first
|
36
|
+
raise StandardError, "Editor not found. Please set your EDITOR env variable" if editor.nil?
|
37
|
+
editor
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.secure_file_delete args
|
41
|
+
file = File.open(args[:file], 'r+')
|
42
|
+
num_bytes = args[:num_bytes]
|
43
|
+
[0xff, 0x55, 0xaa, 0x00].each do |byte|
|
44
|
+
file.seek(0, IO::SEEK_SET)
|
45
|
+
num_bytes.times { file.print(byte.chr) }
|
46
|
+
file.fsync
|
47
|
+
end
|
48
|
+
File.delete args[:file]
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.write_tempfile data_to_write
|
52
|
+
file = Tempfile.open('eyaml_edit')
|
53
|
+
path = file.path
|
54
|
+
file.close!
|
55
|
+
|
56
|
+
file = File.open(path, "w")
|
57
|
+
file.puts data_to_write
|
58
|
+
file.close
|
59
|
+
|
60
|
+
path
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.write_important_file args
|
64
|
+
filename = args[ :filename ]
|
65
|
+
content = args[ :content ]
|
66
|
+
mode = args[ :mode ]
|
67
|
+
if File.file? "#{filename}"
|
68
|
+
raise StandardError, "User aborted" unless Utils::confirm? "Are you sure you want to overwrite \"#{filename}\"?"
|
69
|
+
end
|
70
|
+
open( "#{filename}", "w" ) do |io|
|
71
|
+
io.write(content)
|
72
|
+
end
|
73
|
+
File.chmod( mode, filename ) unless mode.nil?
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.ensure_key_dir_exists key_file
|
77
|
+
key_dir = File.dirname key_file
|
78
|
+
|
79
|
+
unless File.directory? key_dir
|
80
|
+
begin
|
81
|
+
FileUtils.mkdir_p key_dir
|
82
|
+
Utils::info "Created key directory: #{key_dir}"
|
83
|
+
rescue
|
84
|
+
raise StandardError, "Cannot create key directory: #{key_dir}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.find_closest_class args
|
91
|
+
parent_class = args[ :parent_class ]
|
92
|
+
class_name = args[ :class_name ]
|
93
|
+
constants = parent_class.constants
|
94
|
+
candidates = []
|
95
|
+
constants.each do | candidate |
|
96
|
+
candidates << candidate.to_s if candidate.to_s.downcase == class_name.downcase
|
97
|
+
end
|
98
|
+
if candidates.count > 0
|
99
|
+
parent_class.const_get candidates.first
|
100
|
+
else
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.require_dir classdir
|
106
|
+
num_class_hierarchy_levels = self.to_s.split("::").count - 1
|
107
|
+
root_folder = File.dirname(__FILE__) + "/" + Array.new(num_class_hierarchy_levels).fill("..").join("/")
|
108
|
+
class_folder = root_folder + "/" + classdir
|
109
|
+
Dir[File.expand_path("#{class_folder}/*.rb")].uniq.each do |file|
|
110
|
+
# puts "Requiring file: #{file}"
|
111
|
+
require file
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.find_all_subclasses_of args
|
116
|
+
parent_class = args[ :parent_class ]
|
117
|
+
constants = parent_class.constants
|
118
|
+
candidates = []
|
119
|
+
constants.each do | candidate |
|
120
|
+
candidates << candidate.to_s.split('::').last if parent_class.const_get(candidate).class.to_s == "Class"
|
121
|
+
end
|
122
|
+
candidates
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.hiera?
|
126
|
+
"hiera".eql? Eyaml::Options[:source]
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.structure_message messageinfo
|
130
|
+
message = {:from => "hiera-eyaml-core"}
|
131
|
+
case messageinfo.class.to_s
|
132
|
+
when 'Hash'
|
133
|
+
message.merge!(messageinfo)
|
134
|
+
else
|
135
|
+
message.merge!({:msg => messageinfo.to_s})
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.warn messageinfo
|
140
|
+
message = self.structure_message messageinfo
|
141
|
+
message = "[#{message[:from]}] !!! #{message[:msg]}"
|
142
|
+
if self.hiera?
|
143
|
+
Hiera.warn format_message msg
|
144
|
+
else
|
145
|
+
STDERR.puts message
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.info messageinfo
|
150
|
+
message = self.structure_message messageinfo
|
151
|
+
message = "[#{message[:from]}] #{message[:msg]}"
|
152
|
+
if self.hiera?
|
153
|
+
Hiera.debug message if Eyaml.verbosity_level > 0
|
154
|
+
else
|
155
|
+
STDERR.puts message if Eyaml.verbosity_level > 0
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.debug messageinfo
|
160
|
+
message = self.structure_message messageinfo
|
161
|
+
message = "[#{message[:from]}] #{message[:msg]}"
|
162
|
+
if self.hiera?
|
163
|
+
Hiera.debug message if Eyaml.verbosity_level > 1
|
164
|
+
else
|
165
|
+
STDERR.puts message if Eyaml.verbosity_level > 1
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|