prepd 0.1.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|