prepd 0.1.1 → 0.3.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 +5 -5
- data/bin/console +2 -0
- data/files/cluster/Vagrantfile +118 -0
- data/files/cluster/vagrant.yml +52 -0
- data/files/developer/cluster/provision.yml +2 -0
- data/files/machine/build.json +52 -0
- data/files/machine/debian/stretch/iso.json +101 -0
- data/files/machine/debian/stretch/preseed.cfg +404 -0
- data/files/machine/json.rb +26 -0
- data/files/machine/push.json +56 -0
- data/files/machine/rebuild.json +60 -0
- data/files/project/provision.yml +20 -0
- data/files/project/vars.yml +5 -0
- data/files/setup.yml +16 -0
- data/files/setup/README.md +21 -0
- data/files/setup/ansible.cfg +4 -0
- data/files/setup/hosts +1 -0
- data/files/setup/setup.yml +19 -0
- data/files/setup/vars.yml +20 -0
- data/files/workspace/.gitignore +12 -0
- data/files/workspace/README.md +11 -0
- data/files/workspace/clusters/prepd.yml +17 -0
- data/files/workspace/clusters/provision.yml +73 -0
- data/files/workspace/clusters/vagrant.rb +106 -0
- data/files/workspace/clusters/vagrant.yml +18 -0
- data/files/workspace/data/.keep +0 -0
- data/files/workspace/developer/ansible.cfg +4 -0
- data/files/workspace/developer/credentials/.keep +0 -0
- data/files/workspace/developer/hosts +7 -0
- data/files/workspace/developer/machines/provision.yml +9 -0
- data/files/workspace/developer/provision.yml +15 -0
- data/files/workspace/machines/build.yml +34 -0
- data/files/workspace/machines/provision.yml +36 -0
- data/lib/prepd.rb +95 -34
- data/lib/prepd/cli.rb +27 -4
- data/lib/prepd/cli/commands.rb +64 -25
- data/lib/prepd/cli/options_parser.rb +42 -16
- data/lib/prepd/models.rb +7 -261
- data/lib/prepd/models/base.rb +124 -0
- data/lib/prepd/models/cluster.rb +255 -0
- data/lib/prepd/models/data.rb +5 -0
- data/lib/prepd/models/developer.rb +129 -0
- data/lib/prepd/models/machine.rb +146 -0
- data/lib/prepd/models/project.rb +94 -0
- data/lib/prepd/models/setup.rb +48 -0
- data/lib/prepd/models/workspace.rb +51 -0
- data/lib/prepd/version.rb +1 -1
- data/prepd.gemspec +4 -6
- metadata +47 -37
- data/TODO.md +0 -17
- data/lib/prepd/schema.rb +0 -23
data/lib/prepd/models.rb
CHANGED
@@ -1,261 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
before_validation :set_defaults
|
9
|
-
validates :name, :path, presence: true
|
10
|
-
|
11
|
-
after_create :setup
|
12
|
-
after_destroy :destroy_client
|
13
|
-
|
14
|
-
def set_defaults
|
15
|
-
self.path = "#{Prepd.options['DATA_DIR']}/#{name}"
|
16
|
-
end
|
17
|
-
|
18
|
-
def setup
|
19
|
-
FileUtils.mkdir_p(path) unless Dir.exists?(path)
|
20
|
-
end
|
21
|
-
|
22
|
-
def destroy_client
|
23
|
-
FileUtils.rm_rf("#{path}")
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
|
28
|
-
class Project < ActiveRecord::Base
|
29
|
-
attr_accessor :tf_creds, :tf_key, :tf_secret, :ansible_creds, :ansible_key, :ansible_secret
|
30
|
-
|
31
|
-
belongs_to :client, required: true
|
32
|
-
has_many :applications, dependent: :destroy
|
33
|
-
|
34
|
-
validates :name, presence: true, uniqueness: { scope: :client }
|
35
|
-
|
36
|
-
after_create :create_project
|
37
|
-
after_destroy :destroy_project
|
38
|
-
|
39
|
-
#
|
40
|
-
# Initialize the prepd-project or just copy in developer credentials if the project already exists
|
41
|
-
#
|
42
|
-
def create_project
|
43
|
-
if Dir.exists?(path)
|
44
|
-
copy_developer_yml
|
45
|
-
return
|
46
|
-
end
|
47
|
-
setup_git
|
48
|
-
clone_submodules
|
49
|
-
copy_developer_yml
|
50
|
-
generate_credentials
|
51
|
-
encrypt_vault_files
|
52
|
-
end
|
53
|
-
|
54
|
-
#
|
55
|
-
# Destory the VM and remove the project from the file system
|
56
|
-
#
|
57
|
-
def destroy_project
|
58
|
-
Dir.chdir(path) { system('vagrant destroy') }
|
59
|
-
FileUtils.rm_rf(path)
|
60
|
-
end
|
61
|
-
|
62
|
-
#
|
63
|
-
# Clone prepd-project, remove the git history and start with a clean repository
|
64
|
-
#
|
65
|
-
def setup_git
|
66
|
-
Dir.chdir(client.path) { system("git clone git@github.com:rjayroach/prepd-project.git #{name}") }
|
67
|
-
Dir.chdir(path) do
|
68
|
-
FileUtils.rm_rf("#{path}/.git")
|
69
|
-
system('git init')
|
70
|
-
system('git add .')
|
71
|
-
system("git commit -m 'First commit from Prepd'")
|
72
|
-
system("git remote add origin #{repo_url}") if repo_url
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
#
|
77
|
-
# Clone ansible roles and terraform modules
|
78
|
-
#
|
79
|
-
def clone_submodules
|
80
|
-
Dir.chdir("#{path}/ansible") do
|
81
|
-
system('git submodule add git@github.com:rjayroach/ansible-roles.git roles')
|
82
|
-
end
|
83
|
-
Dir.chdir("#{path}/terraform") do
|
84
|
-
system('git submodule add git@github.com:rjayroach/terraform-modules.git modules')
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
#
|
89
|
-
# Copy developer credentials or create them if the file doesn't already exists
|
90
|
-
# TODO: Maybe the creation of developer creds should be done at startup of prepd
|
91
|
-
#
|
92
|
-
def copy_developer_yml
|
93
|
-
return if File.exists?("#{path}/.developer.yml")
|
94
|
-
Dir.chdir(path) do
|
95
|
-
if File.exists?("#{Prepd.work_dir}/developer.yml")
|
96
|
-
FileUtils.cp("#{Prepd.work_dir}/developer.yml", '.developer.yml')
|
97
|
-
elsif File.exists?("#{Dir.home}/.prepd-developer.yml")
|
98
|
-
FileUtils.cp("#{Dir.home}/.prepd-developer.yml", '.developer.yml')
|
99
|
-
else
|
100
|
-
File.open('.developer.yml', 'w') do |f|
|
101
|
-
f.puts('---')
|
102
|
-
f.puts("git_username: #{`git config --get user.name`.chomp}")
|
103
|
-
f.puts("git_email: #{`git config --get user.email`.chomp}")
|
104
|
-
f.puts("docker_username: ")
|
105
|
-
f.puts("docker_password: ")
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
#
|
112
|
-
# Create AWS credential files for Terraform and Ansible, ssh keys and and ansible-vault encryption key
|
113
|
-
# NOTE: The path to credentials is used in the ansible-role prepd
|
114
|
-
#
|
115
|
-
def generate_credentials
|
116
|
-
# self.tf_creds = '/Users/rjayroach/Documents/c2p4/aws/legos-terraform.csv'
|
117
|
-
# self.ansible_creds = '/Users/rjayroach/Documents/c2p4/aws/legos-ansible.csv'
|
118
|
-
generate_tf_creds
|
119
|
-
generate_ansible_creds
|
120
|
-
generate_ssh_keys
|
121
|
-
generate_vault_password
|
122
|
-
end
|
123
|
-
|
124
|
-
def generate_tf_creds
|
125
|
-
self.tf_key, self.tf_secret = CSV.read(tf_creds).last.slice(2,2) if tf_creds
|
126
|
-
unless tf_key and tf_secret
|
127
|
-
STDOUT.puts 'tf_key and tf_secret need to be set (or set tf_creds to path to CSV file)'
|
128
|
-
return
|
129
|
-
end
|
130
|
-
require 'csv'
|
131
|
-
Dir.chdir(path) do
|
132
|
-
File.open('.terraform-vars.txt', 'w') do |f|
|
133
|
-
f.puts("aws_access_key_id = \"#{tf_key}\"")
|
134
|
-
f.puts("aws_secret_access_key = \"#{tf_secret}\"")
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def generate_ansible_creds
|
140
|
-
self.ansible_key, self.ansible_secret = CSV.read(ansible_creds).last.slice(2,2) if ansible_creds
|
141
|
-
unless ansible_key and ansible_secret
|
142
|
-
STDOUT.puts 'ansible_key and ansible_secret need to be set (or set ansible_creds to path to CSV file)'
|
143
|
-
return
|
144
|
-
end
|
145
|
-
Dir.chdir(path) do
|
146
|
-
File.open('.boto', 'w') do |f|
|
147
|
-
f.puts('[Credentials]')
|
148
|
-
f.puts("aws_access_key_id = #{ansible_key}")
|
149
|
-
f.puts("aws_secret_access_key = #{ansible_secret}")
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
#
|
155
|
-
# Generate a key pair to be used as the EC2 key pair
|
156
|
-
#
|
157
|
-
def generate_ssh_keys(file_name = '.id_rsa')
|
158
|
-
Dir.chdir(path) { system("ssh-keygen -b 2048 -t rsa -f #{file_name} -q -N '' -C 'ansible@#{name}.#{client.name}.local'") }
|
159
|
-
end
|
160
|
-
|
161
|
-
#
|
162
|
-
# Generate the key to encrypt ansible-vault files
|
163
|
-
#
|
164
|
-
def generate_vault_password(file_name = '.vault-password.txt')
|
165
|
-
require 'securerandom'
|
166
|
-
Dir.chdir(path) { File.open(file_name, 'w') { |f| f.puts(SecureRandom.uuid) } }
|
167
|
-
end
|
168
|
-
|
169
|
-
#
|
170
|
-
# Use ansible-vault to encrypt the inventory group_vars
|
171
|
-
#
|
172
|
-
def encrypt_vault_files
|
173
|
-
Dir.chdir("#{path}/ansible") do
|
174
|
-
%w(all development local production staging).each do |env|
|
175
|
-
system("ansible-vault encrypt inventory/group_vars/#{env}/vault")
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
def encrypt(mode = :vault)
|
181
|
-
return unless executable?('gpg')
|
182
|
-
Dir.chdir(path) do
|
183
|
-
system "tar cf #{archive(:credentials)} #{file_list(mode)}"
|
184
|
-
end
|
185
|
-
system "gpg -c #{archive(:credentials)}"
|
186
|
-
FileUtils.rm(archive(:credentials))
|
187
|
-
"File created: #{archive(:credentials)}.gpg"
|
188
|
-
end
|
189
|
-
|
190
|
-
def encrypt_data
|
191
|
-
return unless executable?('gpg')
|
192
|
-
archive_path = "#{path}/#{client.name}-#{name}-data.tar"
|
193
|
-
Dir.chdir(path) do
|
194
|
-
system "tar cf #{archive_path} data"
|
195
|
-
end
|
196
|
-
system "gpg -c #{archive_path}"
|
197
|
-
FileUtils.rm(archive_path)
|
198
|
-
FileUtils.mv("#{archive_path}.gpg", "#{archive(:data)}.gpg")
|
199
|
-
"File created: #{archive(:data)}.gpg"
|
200
|
-
end
|
201
|
-
|
202
|
-
def decrypt(type = :credentials)
|
203
|
-
return unless %i(credentials data).include? type
|
204
|
-
return unless executable?('gpg')
|
205
|
-
unless File.exists?("#{archive(type)}.gpg")
|
206
|
-
STDOUT.puts "File not found: #{archive(type)}.gpg"
|
207
|
-
return
|
208
|
-
end
|
209
|
-
system "gpg #{archive(type)}.gpg"
|
210
|
-
Dir.chdir(path) do
|
211
|
-
system "tar xf #{archive(type)}"
|
212
|
-
end
|
213
|
-
FileUtils.rm(archive(type))
|
214
|
-
"File processed: #{archive(type)}.gpg"
|
215
|
-
end
|
216
|
-
|
217
|
-
def executable?(name = 'gpg')
|
218
|
-
require 'mkmf'
|
219
|
-
rv = find_executable(name)
|
220
|
-
STDOUT.puts "#{name} executable not found" unless rv
|
221
|
-
FileUtils.rm('mkmf.log')
|
222
|
-
rv
|
223
|
-
end
|
224
|
-
|
225
|
-
def file_list(mode)
|
226
|
-
return ".boto .id_rsa .id_rsa.pub .terraform-vars.txt .vault-password.txt" if mode.eql?(:all)
|
227
|
-
".vault-password.txt"
|
228
|
-
end
|
229
|
-
|
230
|
-
def archive(type = :credentials)
|
231
|
-
"#{data_path}/#{client.name}-#{name}-#{type}.tar"
|
232
|
-
end
|
233
|
-
|
234
|
-
def data_path
|
235
|
-
"#{path}/data"
|
236
|
-
end
|
237
|
-
|
238
|
-
def path
|
239
|
-
"#{client.path}/#{name}"
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
|
244
|
-
class Application < ActiveRecord::Base
|
245
|
-
belongs_to :project, required: true
|
246
|
-
|
247
|
-
validates :name, presence: true, uniqueness: { scope: :project }
|
248
|
-
|
249
|
-
after_create :setup
|
250
|
-
|
251
|
-
def setup
|
252
|
-
Dir.chdir("#{project.path}/ansible") do
|
253
|
-
FileUtils.cp_r('application', name)
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
def path
|
258
|
-
"#{project.path}/ansible/#{name}"
|
259
|
-
end
|
260
|
-
end
|
261
|
-
end
|
1
|
+
require 'prepd/models/base'
|
2
|
+
require 'prepd/models/setup'
|
3
|
+
require 'prepd/models/cluster'
|
4
|
+
require 'prepd/models/developer'
|
5
|
+
require 'prepd/models/machine'
|
6
|
+
require 'prepd/models/project'
|
7
|
+
require 'prepd/models/workspace'
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Prepd
|
2
|
+
class Base
|
3
|
+
include ActiveModel::Model
|
4
|
+
include ActiveModel::Validations::Callbacks
|
5
|
+
extend ActiveModel::Callbacks
|
6
|
+
|
7
|
+
define_model_callbacks :create
|
8
|
+
|
9
|
+
def create
|
10
|
+
run_callbacks :create do
|
11
|
+
# Your create action methods here
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module Component
|
17
|
+
extend ActiveSupport::Concern
|
18
|
+
|
19
|
+
included do
|
20
|
+
attr_accessor :name
|
21
|
+
|
22
|
+
validates :name, presence: true
|
23
|
+
validate :component_directory_does_not_exist
|
24
|
+
end
|
25
|
+
|
26
|
+
def component_directory_does_not_exist
|
27
|
+
return if Prepd.config.force
|
28
|
+
errors.add(:directory_exists, component_dir) if Dir.exists?(component_dir)
|
29
|
+
end
|
30
|
+
|
31
|
+
def in_component_dir
|
32
|
+
in_component_root do
|
33
|
+
Dir.chdir(name) { yield }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def component_dir
|
38
|
+
"#{component_root}/#{name}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def in_component_root(dir = self.class::WORK_DIR)
|
42
|
+
in_workspace_root do
|
43
|
+
Dir.chdir(dir) { yield }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def component_root
|
48
|
+
"#{workspace_root}/#{self.class::WORK_DIR}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def in_workspace_root
|
52
|
+
raise StandardError, 'Not a prepd workspace' if workspace_root.nil?
|
53
|
+
Dir.chdir(workspace_root) { yield }
|
54
|
+
end
|
55
|
+
|
56
|
+
def workspace_root
|
57
|
+
path = Pathname.new(Prepd.config.working_dir)
|
58
|
+
until path.root?
|
59
|
+
break path if File.exists?("#{path}/prepd-workspace.yml")
|
60
|
+
path = path.parent
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def files_dir
|
65
|
+
"#{Prepd.files_dir}/#{self.class::WORK_DIR}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def klass_name
|
69
|
+
binding.pry
|
70
|
+
"#{Prepd.files_dir}/#{self.class::WORK_DIR}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
=begin
|
76
|
+
require 'yaml'
|
77
|
+
require 'erb'
|
78
|
+
|
79
|
+
module Prepd
|
80
|
+
class Base < ActiveRecord::Base
|
81
|
+
self.abstract_class = true
|
82
|
+
|
83
|
+
attr_accessor :config
|
84
|
+
|
85
|
+
after_initialize :set_config
|
86
|
+
|
87
|
+
def set_config
|
88
|
+
self.config = Prepd.config
|
89
|
+
end
|
90
|
+
|
91
|
+
def as_json(options = {})
|
92
|
+
super(except: [:created_at, :updated_at])
|
93
|
+
end
|
94
|
+
|
95
|
+
def kind
|
96
|
+
self.class.name.split('::').last.downcase
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_yaml
|
100
|
+
{ 'kind' => kind, 'data' => for_yaml }.to_yaml
|
101
|
+
end
|
102
|
+
|
103
|
+
def from_yaml
|
104
|
+
File.exists?(config_file_path) ? YAML.load_file(config_file_path) : {}
|
105
|
+
end
|
106
|
+
|
107
|
+
def write_config
|
108
|
+
FileUtils.mkdir_p("#{config_dir}/vars") unless Dir.exists?("#{config_dir}/vars")
|
109
|
+
File.open(config_file_path, 'w') { |f| f.write(to_yaml) }
|
110
|
+
end
|
111
|
+
|
112
|
+
def config_file_path
|
113
|
+
"#{config_dir}/vars/setup.yml"
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# Remove the project from the file system
|
118
|
+
#
|
119
|
+
def delete_config_dir
|
120
|
+
FileUtils.rm_rf(config_dir)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
=end
|
@@ -0,0 +1,255 @@
|
|
1
|
+
module Prepd
|
2
|
+
class Cluster < Base
|
3
|
+
WORK_DIR = 'clusters'
|
4
|
+
include Prepd::Component
|
5
|
+
|
6
|
+
after_create :create_cluster, :initialize_cluster
|
7
|
+
|
8
|
+
def create_cluster
|
9
|
+
in_component_root do
|
10
|
+
FileUtils.rm_rf(name) if Prepd.config.force
|
11
|
+
FileUtils.mkdir_p(name)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize_cluster
|
16
|
+
in_component_dir do
|
17
|
+
FileUtils.cp_r("#{Prepd.files_dir}/cluster/.", '.')
|
18
|
+
end
|
19
|
+
# in_component_root('developer') do
|
20
|
+
# FileUtils.mkdir_p(name)
|
21
|
+
# Dir.chdir(name) do
|
22
|
+
# FileUtils.cp_r("#{Prepd.files_dir}/developer/cluster/.", '.')
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
in_component_root('projects') do
|
26
|
+
FileUtils.mkdir_p(name)
|
27
|
+
Dir.chdir(name) { FileUtils.cp_r("#{Prepd.files_dir}/project/.", '.') }
|
28
|
+
end
|
29
|
+
in_component_root('data') do
|
30
|
+
FileUtils.mkdir_p(name)
|
31
|
+
Dir.chdir(name) { FileUtils.touch('.keep') }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def up
|
36
|
+
in_component_dir { vagrant up }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
=begin
|
42
|
+
require 'erb'
|
43
|
+
module Prepd
|
44
|
+
class Machine < Base
|
45
|
+
VAGRANTFILE = 'Vagrantfile'.freeze
|
46
|
+
NAME = %x(hostname -f).split('.')[1].freeze
|
47
|
+
|
48
|
+
has_many :machine_projects
|
49
|
+
has_many :projects, through: :machine_projects
|
50
|
+
|
51
|
+
after_save :write_vagrantfile, :write_config
|
52
|
+
before_destroy :destroy_vm, :delete_config_dir
|
53
|
+
|
54
|
+
validates :name, presence: true, uniqueness: true # "You must supply APP_PATH" unless name
|
55
|
+
|
56
|
+
def self.ref
|
57
|
+
find_by(name: NAME)
|
58
|
+
end
|
59
|
+
|
60
|
+
def write_vagrantfile
|
61
|
+
FileUtils.mkdir_p(config_dir) unless Dir.exists?(config_dir)
|
62
|
+
File.open("#{config_dir}/#{VAGRANTFILE}", 'w') { |f| f.write(ERB.new(vagrantfile_template).result(binding)) }
|
63
|
+
end
|
64
|
+
|
65
|
+
def vagrantfile_template
|
66
|
+
File.read("#{Prepd.files_dir}/machine/#{VAGRANTFILE}")
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# Destory the VM
|
71
|
+
#
|
72
|
+
def destroy_vm
|
73
|
+
yes = config.yes ? ' --force' : ''
|
74
|
+
processed = nil
|
75
|
+
Dir.chdir(config_dir) { processed = system("vagrant destroy#{yes}") }
|
76
|
+
# TODO: If the vagrant destory is canceled then immediately return from this method
|
77
|
+
unless processed
|
78
|
+
errors.add(:destroy, vm: 'error destroying virutal machine')
|
79
|
+
throw :abort
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def up
|
84
|
+
processed, response = nil
|
85
|
+
Dir.chdir(config_dir) do
|
86
|
+
processed = system("vagrant up")
|
87
|
+
subdomain, x, y, domain = Dir.pwd.split('/').reverse[0..3]
|
88
|
+
response = "ssh node0.#{subdomain}.#{domain}.local"
|
89
|
+
end
|
90
|
+
response
|
91
|
+
end
|
92
|
+
|
93
|
+
def config_dir
|
94
|
+
"#{config.prepd_dir}/config/machines/#{name}"
|
95
|
+
end
|
96
|
+
|
97
|
+
# as_json with projects array included
|
98
|
+
def for_yaml
|
99
|
+
as_json.merge({ 'projects' => projects.as_json })
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
# attr_accessor :tf_creds, :tf_key, :tf_secret, :ansible_creds, :ansible_key, :ansible_secret
|
104
|
+
#
|
105
|
+
# Copy developer credentials or create them if the file doesn't already exists
|
106
|
+
# TODO: Maybe the creation of developer creds should be done at startup of prepd
|
107
|
+
#
|
108
|
+
def copy_developer_yml
|
109
|
+
return if File.exists?("#{path}/.developer.yml")
|
110
|
+
Dir.chdir(path) do
|
111
|
+
if File.exists?("#{Prepd.config_dir}/developer.yml")
|
112
|
+
FileUtils.cp("#{Prepd.config_dir}/developer.yml", '.developer.yml')
|
113
|
+
elsif File.exists?("#{Dir.home}/.prepd-developer.yml")
|
114
|
+
FileUtils.cp("#{Dir.home}/.prepd-developer.yml", '.developer.yml')
|
115
|
+
else
|
116
|
+
File.open('.developer.yml', 'w') do |f|
|
117
|
+
f.puts('---')
|
118
|
+
f.puts("git_username: #{`git config --get user.name`.chomp}")
|
119
|
+
f.puts("git_email: #{`git config --get user.email`.chomp}")
|
120
|
+
f.puts("docker_username: ")
|
121
|
+
f.puts("docker_password: ")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
#
|
128
|
+
# Create AWS credential files for Terraform and Ansible, ssh keys and and ansible-vault encryption key
|
129
|
+
# NOTE: The path to credentials is used in the ansible-role prepd
|
130
|
+
#
|
131
|
+
def generate_credentials
|
132
|
+
# self.tf_creds = '/Users/rjayroach/Documents/c2p4/aws/legos-terraform.csv'
|
133
|
+
# self.ansible_creds = '/Users/rjayroach/Documents/c2p4/aws/legos-ansible.csv'
|
134
|
+
generate_tf_creds
|
135
|
+
generate_ansible_creds
|
136
|
+
generate_ssh_keys
|
137
|
+
generate_vault_password
|
138
|
+
end
|
139
|
+
|
140
|
+
def generate_tf_creds
|
141
|
+
self.tf_key, self.tf_secret = CSV.read(tf_creds).last.slice(2,2) if tf_creds
|
142
|
+
unless tf_key and tf_secret
|
143
|
+
STDOUT.puts 'tf_key and tf_secret need to be set (or set tf_creds to path to CSV file)'
|
144
|
+
return
|
145
|
+
end
|
146
|
+
require 'csv'
|
147
|
+
Dir.chdir(path) do
|
148
|
+
File.open('.terraform-vars.txt', 'w') do |f|
|
149
|
+
f.puts("aws_access_key_id = \"#{tf_key}\"")
|
150
|
+
f.puts("aws_secret_access_key = \"#{tf_secret}\"")
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def generate_ansible_creds
|
156
|
+
self.ansible_key, self.ansible_secret = CSV.read(ansible_creds).last.slice(2,2) if ansible_creds
|
157
|
+
unless ansible_key and ansible_secret
|
158
|
+
STDOUT.puts 'ansible_key and ansible_secret need to be set (or set ansible_creds to path to CSV file)'
|
159
|
+
return
|
160
|
+
end
|
161
|
+
Dir.chdir(path) do
|
162
|
+
File.open('.boto', 'w') do |f|
|
163
|
+
f.puts('[Credentials]')
|
164
|
+
f.puts("aws_access_key_id = #{ansible_key}")
|
165
|
+
f.puts("aws_secret_access_key = #{ansible_secret}")
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
#
|
171
|
+
# Generate a key pair to be used as the EC2 key pair
|
172
|
+
#
|
173
|
+
def generate_ssh_keys(file_name = '.id_rsa')
|
174
|
+
Dir.chdir(path) { system("ssh-keygen -b 2048 -t rsa -f #{file_name} -q -N '' -C 'ansible@#{name}.#{client.name}.local'") }
|
175
|
+
end
|
176
|
+
|
177
|
+
#
|
178
|
+
# Generate the key to encrypt ansible-vault files
|
179
|
+
#
|
180
|
+
def generate_vault_password(file_name = '.vault-password.txt')
|
181
|
+
require 'securerandom'
|
182
|
+
Dir.chdir(path) { File.open(file_name, 'w') { |f| f.puts(SecureRandom.uuid) } }
|
183
|
+
end
|
184
|
+
|
185
|
+
#
|
186
|
+
# Use ansible-vault to encrypt the inventory group_vars
|
187
|
+
#
|
188
|
+
def encrypt_vault_files
|
189
|
+
Dir.chdir("#{path}/ansible") do
|
190
|
+
%w(all development local production staging).each do |env|
|
191
|
+
system("ansible-vault encrypt inventory/group_vars/#{env}/vault")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def encrypt(mode = :vault)
|
197
|
+
return unless executable?('gpg')
|
198
|
+
Dir.chdir(path) do
|
199
|
+
system "tar cf #{archive(:credentials)} #{file_list(mode)}"
|
200
|
+
end
|
201
|
+
system "gpg -c #{archive(:credentials)}"
|
202
|
+
FileUtils.rm(archive(:credentials))
|
203
|
+
"File created: #{archive(:credentials)}.gpg"
|
204
|
+
end
|
205
|
+
|
206
|
+
def encrypt_data
|
207
|
+
return unless executable?('gpg')
|
208
|
+
archive_path = "#{path}/#{client.name}-#{name}-data.tar"
|
209
|
+
Dir.chdir(path) do
|
210
|
+
system "tar cf #{archive_path} data"
|
211
|
+
end
|
212
|
+
system "gpg -c #{archive_path}"
|
213
|
+
FileUtils.rm(archive_path)
|
214
|
+
FileUtils.mv("#{archive_path}.gpg", "#{archive(:data)}.gpg")
|
215
|
+
"File created: #{archive(:data)}.gpg"
|
216
|
+
end
|
217
|
+
|
218
|
+
def decrypt(type = :credentials)
|
219
|
+
return unless %i(credentials data).include? type
|
220
|
+
return unless executable?('gpg')
|
221
|
+
unless File.exists?("#{archive(type)}.gpg")
|
222
|
+
STDOUT.puts "File not found: #{archive(type)}.gpg"
|
223
|
+
return
|
224
|
+
end
|
225
|
+
system "gpg #{archive(type)}.gpg"
|
226
|
+
Dir.chdir(path) do
|
227
|
+
system "tar xf #{archive(type)}"
|
228
|
+
end
|
229
|
+
FileUtils.rm(archive(type))
|
230
|
+
"File processed: #{archive(type)}.gpg"
|
231
|
+
end
|
232
|
+
|
233
|
+
def executable?(name = 'gpg')
|
234
|
+
require 'mkmf'
|
235
|
+
rv = find_executable(name)
|
236
|
+
STDOUT.puts "#{name} executable not found" unless rv
|
237
|
+
FileUtils.rm('mkmf.log')
|
238
|
+
rv
|
239
|
+
end
|
240
|
+
|
241
|
+
def file_list(mode)
|
242
|
+
return ".boto .id_rsa .id_rsa.pub .terraform-vars.txt .vault-password.txt" if mode.eql?(:all)
|
243
|
+
".vault-password.txt"
|
244
|
+
end
|
245
|
+
|
246
|
+
def archive(type = :credentials)
|
247
|
+
"#{data_path}/#{client.name}-#{name}-#{type}.tar"
|
248
|
+
end
|
249
|
+
|
250
|
+
def data_path
|
251
|
+
"#{path}/data"
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
=end
|