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
@@ -0,0 +1,18 @@
|
|
1
|
+
# applies to all clusters
|
2
|
+
# NOTE: Dir.pwd returns the directory of the Vagrantfile
|
3
|
+
---
|
4
|
+
settings:
|
5
|
+
workspace: <%= Pathname.new(Dir.pwd).parent.parent %>
|
6
|
+
boxes_dir: <%= Pathname.new(Dir.pwd).parent.parent %>/machines/boxes
|
7
|
+
# boxes_dir: <%= Dir.home %>/.prepd/share/packer/debian/stretch/boxes
|
8
|
+
# boxes_dir: https://s3-ap-southeast-1.amazonaws.com/c2p4-storage/boxes
|
9
|
+
name: <%= Dir.pwd.split('/').last %>
|
10
|
+
projects_name: <%= Dir.pwd.split('/').last %>
|
11
|
+
|
12
|
+
boxes:
|
13
|
+
development:
|
14
|
+
box: <%= workspace['name'] %>/debian-stretch-amd64-development
|
15
|
+
box_url: <%= settings['boxes_dir'] %>/debian-stretch-amd64-development.json
|
16
|
+
minikube:
|
17
|
+
box: <%= workspace['name'] %>/debian-stretch-amd64-minikube
|
18
|
+
box_url: <%= settings['boxes_dir'] %>/debian-stretch-amd64-minikube.json
|
File without changes
|
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ansible-playbook
|
2
|
+
---
|
3
|
+
- hosts: development
|
4
|
+
tasks:
|
5
|
+
- name: Include vars
|
6
|
+
include_vars:
|
7
|
+
file: vars.yml
|
8
|
+
|
9
|
+
- include_role:
|
10
|
+
name: prepd/yadr
|
11
|
+
|
12
|
+
- include_role:
|
13
|
+
name: prepd/credentials
|
14
|
+
vars:
|
15
|
+
credentials_src_dirs: credentials
|
@@ -0,0 +1,34 @@
|
|
1
|
+
---
|
2
|
+
aws:
|
3
|
+
profile: vagrant-s3
|
4
|
+
s3_bucket: my-storage-bucket
|
5
|
+
s3_region: ap-southeast-1
|
6
|
+
box_dir: boxes
|
7
|
+
|
8
|
+
os_images:
|
9
|
+
debian_stretch_amd64:
|
10
|
+
base_dir: debian/stretch
|
11
|
+
base_name: debian-stretch-amd64
|
12
|
+
iso_url: https://cdimage.debian.org/debian-cd/9.4.0/amd64/iso-cd/debian-9.4.0-amd64-xfce-CD-1.iso
|
13
|
+
iso_checksum: 6715c8c0bedf77c8eef2e8732e117db6
|
14
|
+
|
15
|
+
images:
|
16
|
+
# 1) Start by creating a base image from the OS's official ISO and add ansible
|
17
|
+
base:
|
18
|
+
source:
|
19
|
+
os_image: debian_stretch_amd64
|
20
|
+
provisioner: <%= Dir.pwd %>/provision.yml
|
21
|
+
# 2) Customize the base image to the developer's requirements
|
22
|
+
developer-base:
|
23
|
+
source:
|
24
|
+
image: base
|
25
|
+
provisioner: <%= Pathname.new(Dir.pwd).parent.to_s %>/developer/machines/provision.yml
|
26
|
+
# 3) All additional images are derived from the developer's base image
|
27
|
+
development:
|
28
|
+
source:
|
29
|
+
image: developer-base
|
30
|
+
provisioner: <%= Dir.pwd %>/provision.yml
|
31
|
+
minikube:
|
32
|
+
source:
|
33
|
+
image: developer-base
|
34
|
+
provisioner: <%= Dir.pwd %>/provision.yml
|
@@ -0,0 +1,36 @@
|
|
1
|
+
---
|
2
|
+
- hosts: base
|
3
|
+
tasks:
|
4
|
+
- include_role:
|
5
|
+
name: prepd/packer/base-provision
|
6
|
+
- include_role:
|
7
|
+
name: prepd/ansible
|
8
|
+
|
9
|
+
- hosts: development
|
10
|
+
tasks:
|
11
|
+
- include_role:
|
12
|
+
name: prepd/ruby
|
13
|
+
- include_role:
|
14
|
+
name: prepd/docker
|
15
|
+
- name: Install kubectl
|
16
|
+
include_role:
|
17
|
+
name: prepd/k8s/kubectl
|
18
|
+
- name: Install helm
|
19
|
+
include_role:
|
20
|
+
name: prepd/k8s/helm
|
21
|
+
|
22
|
+
- hosts: minikube
|
23
|
+
tasks:
|
24
|
+
- include_role:
|
25
|
+
name: prepd/docker
|
26
|
+
- include_role:
|
27
|
+
name: prepd/k8s/kubectl
|
28
|
+
- include_role:
|
29
|
+
name: prepd/k8s/minikube
|
30
|
+
vars:
|
31
|
+
# See: https://github.com/kubernetes/minikube/issues/2549
|
32
|
+
k8s_minikube_bin_url: https://storage.googleapis.com/minikube-builds/2550/minikube-linux-amd64
|
33
|
+
- include_role:
|
34
|
+
name: prepd/k8s/minikube
|
35
|
+
tasks_from: start
|
36
|
+
- command: minikube delete
|
data/lib/prepd.rb
CHANGED
@@ -1,47 +1,108 @@
|
|
1
|
-
require 'prepd/version'
|
2
|
-
require 'dotenv'
|
3
|
-
require 'active_record'
|
4
|
-
require 'sqlite3'
|
5
1
|
require 'fileutils'
|
2
|
+
require 'active_record'
|
6
3
|
|
7
4
|
module Prepd
|
8
|
-
|
9
|
-
|
5
|
+
class StringInquirer < String
|
6
|
+
# Copied from ActiveSupport::StringInquirer
|
7
|
+
def method_missing(method_name, *arguments)
|
8
|
+
if method_name[-1] == '?'
|
9
|
+
self == method_name[0..-2]
|
10
|
+
else
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
10
15
|
|
11
|
-
def self.
|
16
|
+
def self.env; @env; end
|
17
|
+
def self.env=(env); @env = env; end
|
12
18
|
|
13
|
-
def self.
|
19
|
+
def self.config_dir; @config_dir end
|
14
20
|
|
15
|
-
def self.
|
16
|
-
|
17
|
-
'VERSION' => '1',
|
18
|
-
'DATA_DIR' => "#{Dir.home}/prepd",
|
19
|
-
'VAGRANT_BASE_BOX' => 'debian/contrib-jessie64'
|
20
|
-
}
|
21
|
+
def self.config_dir=(dir)
|
22
|
+
@config_dir = dir
|
21
23
|
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
25
|
+
def self.config_file; "#{config_dir}/config.yml"; end
|
26
|
+
|
27
|
+
def self.default_config
|
28
|
+
{ version: 1 }
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.register_workspace(dir)
|
32
|
+
config.workspaces << dir
|
33
|
+
write_config_file
|
33
34
|
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
default_settings.each { |key, value| f.puts("#{key}=#{value}") }
|
36
|
+
def self.verify_workspaces
|
37
|
+
config.workspaces ||= []
|
38
|
+
config.workspaces.each do |dir|
|
39
|
+
next if File.exists?(File.expand_path("#{dir}/prepd-workspace.yml"))
|
40
|
+
config.workspaces -= [dir]
|
41
41
|
end
|
42
|
+
write_config_file
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.base_config
|
46
|
+
write_config_file unless File.exists?(config_file)
|
47
|
+
default_config.merge(YAML.load(File.read(config_file)))
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.write_config_file
|
51
|
+
FileUtils.mkdir_p(config_dir) unless Dir.exists?(config_dir)
|
52
|
+
File.open(config_file, 'w') { |f| f.write(YAML.dump(writable_config)) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.writable_config
|
56
|
+
config.to_h.select { |k| %i(version workspaces).include?(k) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.config=(config)
|
60
|
+
@config = config
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.config; @config; end
|
64
|
+
|
65
|
+
def self.cli_options=(config)
|
66
|
+
@cli_options = config
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.cli_options; @cli_options; end
|
70
|
+
|
71
|
+
def self.log(message)
|
72
|
+
STDOUT.puts(message)
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.files_dir
|
76
|
+
"#{Pathname.new(File.dirname(__FILE__)).parent}/files"
|
42
77
|
end
|
43
|
-
Dotenv.load(config)
|
44
|
-
end
|
45
78
|
|
46
|
-
|
47
|
-
|
79
|
+
# Probe system for whether it is virutal or not and default accordingly
|
80
|
+
# hostnamectl | grep Virtualization will return a string when the string is found (vm) and '' when not (host)
|
81
|
+
# it will fail on apple machines b/c hostnamectl is not a valid command which means it is the host
|
82
|
+
def self.machine_is_host?
|
83
|
+
return true unless system('hostnamectl > /dev/null 2>&1')
|
84
|
+
%x('hostnamectl').index('Virtualization').nil?
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
def self.create_password_file(config_dir)
|
89
|
+
password_dir = "#{config_dir}/vault-keys"
|
90
|
+
password_file = "#{password_dir}/password.txt"
|
91
|
+
return if File.exists?(password_file)
|
92
|
+
FileUtils.mkdir_p(password_dir) unless Dir.exists? password_dir
|
93
|
+
write_password_file(password_file)
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Generate the key to encrypt ansible-vault files
|
98
|
+
#
|
99
|
+
def self.write_password_file(file_name = 'password.txt')
|
100
|
+
require 'securerandom'
|
101
|
+
File.open(file_name, 'w') { |f| f.puts(SecureRandom.uuid) }
|
102
|
+
nil
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.git_log
|
106
|
+
config.verbose ? '' : '--quiet'
|
107
|
+
end
|
108
|
+
end
|
data/lib/prepd/cli.rb
CHANGED
@@ -1,8 +1,31 @@
|
|
1
1
|
require 'pry'
|
2
|
-
require '
|
2
|
+
require 'ostruct'
|
3
3
|
require 'prepd/cli/options_parser'
|
4
4
|
require 'prepd/cli/commands'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
module Prepd
|
7
|
+
# Parse any command line arguments
|
8
|
+
Prepd.cli_options = OpenStruct.new(Cli::OptionsParser.new.parse)
|
9
|
+
|
10
|
+
# Load the default config, override with config file valuse and finally override with any command line options
|
11
|
+
Prepd.config_dir = Prepd.cli_options.config_dir || "#{Dir.home}/.prepd"
|
12
|
+
Prepd.config = OpenStruct.new(base_config.merge(cli_options.to_h))
|
13
|
+
config.command = StringInquirer.new(ARGV[0] ? ARGV.shift : 'cli')
|
14
|
+
|
15
|
+
config.env = StringInquirer.new(Prepd.cli_options.env || 'production' )
|
16
|
+
config.working_dir ||= Dir.pwd
|
17
|
+
|
18
|
+
# Set config values based on machine probe, defaults, config file and cli arguments
|
19
|
+
config.machine_type = StringInquirer.new(machine_is_host? ? 'host' : 'vm')
|
20
|
+
Prepd.verify_workspaces
|
21
|
+
|
22
|
+
# Process the command or invoke the console
|
23
|
+
if config.command.cli?
|
24
|
+
Pry.start(Prepd::Command, prompt: [proc { 'prepd> '}])
|
25
|
+
elsif Command.methods(false).include?(config.command.to_sym)
|
26
|
+
STDOUT.puts(Command.send(config.command))
|
27
|
+
else
|
28
|
+
# TODO: show the 'runtime' help
|
29
|
+
STDOUT.puts("#{config.command} - No such command. Valid commands are #{Command.methods(false).join(', ')}")
|
30
|
+
end
|
31
|
+
end
|
data/lib/prepd/cli/commands.rb
CHANGED
@@ -1,37 +1,76 @@
|
|
1
|
+
require 'prepd/models'
|
2
|
+
|
1
3
|
module Prepd
|
2
|
-
|
3
|
-
|
4
|
-
end
|
5
|
-
def self.options; @options; end
|
4
|
+
class Command
|
5
|
+
def self.config; Prepd.config; end
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
def self.list(type = ARGV.shift)
|
8
|
+
return 'invalid type' unless %w(clusters projects machines).include? type
|
9
|
+
"Prepd::#{type.classify}".constantize.new.in_component_root { Dir.glob('*') }
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
def self.new(type = ARGV.shift, name = ARGV.shift, *args)
|
13
|
+
cr = Creator.new(type: type)
|
14
|
+
# TODO: this should display the appropriate help if name is not supplied
|
15
|
+
return cr.errors.full_messages.join("\n") unless cr.valid?
|
16
|
+
# return 'Must supply type' unless type
|
17
|
+
# return 'Must supply APP_PATH' unless name
|
18
|
+
obj = cr.klass.new(name: name)
|
19
|
+
return obj.errors.full_messages.join("\n") unless obj.valid?
|
20
|
+
obj.create
|
21
|
+
nil
|
22
|
+
end
|
14
23
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
24
|
+
def self.build(name = ARGV.shift)
|
25
|
+
cr = Machine.new(name: name)
|
26
|
+
return cr.errors.full_messages.join("\n") unless cr.valid?
|
27
|
+
cr.create
|
28
|
+
nil
|
29
|
+
end
|
19
30
|
|
20
|
-
|
31
|
+
def self.show(name = nil)
|
32
|
+
name ||= ARGV[0] || Dir.pwd.split('/').last
|
33
|
+
return unless obj = klass.find_by(name: name)
|
34
|
+
YAML.load(obj.to_yaml)
|
35
|
+
end
|
21
36
|
|
22
|
-
|
37
|
+
def self.up(name = ARGV.shift)
|
38
|
+
Cluster.new(name: name).up
|
39
|
+
end
|
23
40
|
|
24
|
-
|
25
|
-
|
41
|
+
def self.rm(name = nil)
|
42
|
+
name ||= ARGV[0] || Dir.pwd.split('/').last
|
43
|
+
return unless obj = klass.find_by(name: name)
|
44
|
+
obj.destroy ? nil : obj.errors.full_messages.join('. ')
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Setup a new installation of prepd on a workstation
|
49
|
+
#
|
50
|
+
def self.setup
|
51
|
+
obj = Setup.new
|
52
|
+
return obj.errors.full_messages.join("\n") unless obj.valid?
|
53
|
+
obj.create
|
54
|
+
end
|
26
55
|
end
|
27
56
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
57
|
+
class Creator
|
58
|
+
include ActiveModel::Model
|
59
|
+
include ActiveModel::Validations::Callbacks
|
60
|
+
VALID_CLASSES = %w(workspace cluster project).freeze
|
61
|
+
|
62
|
+
attr_accessor :type
|
63
|
+
|
64
|
+
validates :type, presence: true, inclusion: { in: VALID_CLASSES }
|
65
|
+
|
66
|
+
before_validation :set_type_down
|
67
|
+
|
68
|
+
def set_type_down
|
69
|
+
self.type = self.type.downcase
|
70
|
+
end
|
71
|
+
|
72
|
+
def klass
|
73
|
+
Kernel.const_get("Prepd::#{type.capitalize}")
|
33
74
|
end
|
34
|
-
STDOUT.puts 'duh2'
|
35
|
-
nil
|
36
75
|
end
|
37
76
|
end
|
@@ -2,41 +2,67 @@ require 'optparse'
|
|
2
2
|
|
3
3
|
module Prepd::Cli
|
4
4
|
class OptionsParser
|
5
|
-
attr_accessor :options
|
6
|
-
|
7
|
-
def initialize(options = nil)
|
8
|
-
self.options = options || {}
|
9
|
-
end
|
10
|
-
|
11
5
|
def parse
|
6
|
+
options = OpenStruct.new
|
12
7
|
optparse = OptionParser.new do |opts|
|
13
|
-
opts.
|
14
|
-
|
8
|
+
opts.banner = "Usage:\n prepd new AAP_PATH [options]\n\nOptions:"
|
9
|
+
|
10
|
+
opts.on( '--bump=LEVEL', '# Setup the application with development repositories' ) do |value|
|
11
|
+
options.bump = value
|
15
12
|
end
|
16
13
|
|
17
|
-
opts.on( '
|
18
|
-
options
|
14
|
+
opts.on( '--cd=CONFIG_DIR', '# Run from the configuration in directory' ) do |value|
|
15
|
+
options.config_dir = value
|
19
16
|
end
|
20
17
|
|
21
|
-
opts.on( '
|
22
|
-
options
|
18
|
+
opts.on( '--push', '# Push the box to remote S3 bucket' ) do
|
19
|
+
options.push = true
|
23
20
|
end
|
24
21
|
|
25
|
-
opts.on(
|
22
|
+
opts.on( '--dev', '# Setup the application with development repositories' ) do |value|
|
23
|
+
options.env = 'development'
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on( '--dir=DIR', '# Set the working directory' ) do |value|
|
27
|
+
options.working_dir = value
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on( '--force', '# Force operation even if it will cause errors' ) do |value|
|
31
|
+
options.force = true
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on('-h', '--help', '# Display this screen') do
|
35
|
+
# TODO: If Dir.pwd is a prepd project then putput the 'runtime' commands here
|
36
|
+
# Otherwise output the 'prepd new --help' is appropriate
|
26
37
|
puts opts
|
38
|
+
puts "\nExample:\n prepd new ~/my/new/project\n"
|
39
|
+
puts "\n This generates a skeletal prepd installation in ~/my/new/project"
|
27
40
|
exit
|
28
41
|
end
|
29
42
|
|
30
|
-
opts.on('-
|
43
|
+
opts.on( '-m', '--machine', '# Create a new virtual machine' ) do |value|
|
44
|
+
options.create_type = :machine
|
45
|
+
end
|
46
|
+
|
47
|
+
opts.on('-n', '--no-op', '# Show what would happen but do not execute') do
|
31
48
|
options.no_op = true
|
49
|
+
options.verbose = true
|
32
50
|
end
|
33
51
|
|
34
|
-
opts.on('-
|
52
|
+
opts.on( '-p', '--project', '# Create a new project' ) do |value|
|
53
|
+
options.create_type = :project
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.on('-v', '--verbose', '# Display additional information') do
|
35
57
|
options.verbose = true
|
36
58
|
end
|
59
|
+
|
60
|
+
opts.on('--yes', '# Automatically say yes') do
|
61
|
+
options.yes = true
|
62
|
+
end
|
37
63
|
end
|
38
64
|
optparse.parse!
|
39
|
-
options
|
65
|
+
options.to_h
|
40
66
|
end
|
41
67
|
end
|
42
68
|
end
|