asteroid 0.0.1 → 0.0.2
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 +4 -4
- data/.travis.yml +2 -0
- data/Gemfile +1 -0
- data/README.md +45 -4
- data/Rakefile +1 -0
- data/asteroid.gemspec +0 -1
- data/bin/asteroid +4 -2
- data/lib/asteroid.rb +11 -10
- data/lib/asteroid/application.rb +60 -7
- data/lib/asteroid/config.rb +28 -14
- data/lib/asteroid/file_reference.rb +102 -0
- data/lib/asteroid/generator.rb +0 -4
- data/lib/asteroid/instance.rb +29 -9
- data/lib/asteroid/instance/command.rb +71 -36
- data/lib/asteroid/instance/scp.rb +26 -0
- data/lib/asteroid/instance/ssh.rb +2 -1
- data/lib/asteroid/instance/vars.rb +5 -2
- data/lib/asteroid/key_reference.rb +45 -0
- data/lib/asteroid/provider/abstract.rb +16 -1
- data/lib/asteroid/provider/digital_ocean.rb +35 -6
- data/lib/asteroid/provider/mock.rb +36 -14
- data/lib/asteroid/script.rb +3 -57
- data/lib/asteroid/server.rb +44 -25
- data/lib/asteroid/template.rb +19 -7
- data/lib/asteroid/template/liquid.rb +0 -0
- data/lib/asteroid/version.rb +1 -1
- data/sample/.gitignore +2 -0
- data/sample/README.md +1 -0
- data/sample/Rakefile +0 -0
- data/sample/TODO +9 -0
- data/sample/asteroid/files/nginx/available_site.conf.erb +0 -0
- data/sample/asteroid/files/nginx/nginx.conf +1 -0
- data/sample/asteroid/scripts/ubuntu.aster +4 -0
- data/sample/asteroid/servers/default.yml +3 -0
- data/sample/asteroid/servers/web.yml +5 -0
- data/sample/config/asteroid.rb +9 -0
- data/test/helper.rb +18 -2
- data/test/unit/test_application.rb +17 -0
- data/test/unit/test_file_reference.rb +18 -0
- data/test/unit/test_instance.rb +20 -4
- data/test/unit/test_script_reference.rb +9 -0
- data/test/unit/test_server.rb +46 -2
- data/test/unit/test_template.rb +16 -0
- metadata +24 -17
- data/lib/asteroid/config_file.rb +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5c5cc037af98984058dd5b4f265e016566f8f3f
|
4
|
+
data.tar.gz: f63bd8fd4eb00c4ae7fc2b081c6c132ff8910040
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b3a7534a6668e92a89ac8c605502017e5bbafe4fa930a856bfc5e6c037bae2eedcd7fe83bbc4c92482bdfd83df1ffb9aa536d656f76b55dbe7912e1d0d3d27d
|
7
|
+
data.tar.gz: 3d79c608d88e060845516c5424bd1374d04769014acec7961a701ca64de60274c8ce061cb0d6e080776c29f0476556e1710d879345ed680ce90801fcf19a0d20
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,50 @@
|
|
1
1
|
# Asteroid
|
2
2
|
|
3
|
+
[](http://badge.fury.io/rb/asteroid)
|
3
4
|
|
4
|
-
|
5
|
+
Asteroid is a server management framework built in Ruby. It is heavily inspired by [Fucking Shell Scripts](http://fuckingshellscripts.org).
|
6
|
+
|
7
|
+
### Creating a new Project
|
8
|
+
|
9
|
+
```sh
|
10
|
+
gem install asteroid
|
11
|
+
asteroid new <project_name>
|
12
|
+
```
|
13
|
+
|
14
|
+
### Things you need to edit
|
15
|
+
|
16
|
+
* `secrets/providers.rb` contains the file that loads providers
|
17
|
+
* `secrets/secrets.yml` is a place to store secrets used elsewhere
|
18
|
+
|
19
|
+
### Create a new Server
|
20
|
+
|
21
|
+
To create a server, create a `.yml` file in `asteroid/servers`. Create one named `web.yml` that looks like this:
|
22
|
+
|
23
|
+
```yaml
|
24
|
+
name: web
|
25
|
+
|
26
|
+
instance_options:
|
27
|
+
size_id: 61 # DigitalOcean 1gb
|
28
|
+
region_id: 12 # DigitalOcean NYC2
|
29
|
+
ssh_key_ids: [1123232]
|
30
|
+
|
31
|
+
commands:
|
32
|
+
after-create:
|
33
|
+
- configure
|
34
|
+
|
35
|
+
configure:
|
36
|
+
- run apt-get upgrade
|
37
|
+
|
38
|
+
```
|
39
|
+
|
40
|
+
### To create an instance
|
41
|
+
|
42
|
+
Run this in your project root
|
43
|
+
|
44
|
+
```sh
|
45
|
+
asteroid server create web
|
46
|
+
```
|
47
|
+
|
48
|
+
If everything is configured you should have a new server in the cloud.
|
5
49
|
|
6
|
-
asteroid new <project>
|
7
50
|
|
8
|
-
# creating new directory
|
9
|
-
#
|
data/Rakefile
CHANGED
data/asteroid.gemspec
CHANGED
data/bin/asteroid
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib/')
|
4
|
+
|
5
|
+
require 'asteroid'
|
4
6
|
require 'asteroid/application'
|
5
7
|
|
6
8
|
boot_file = File.expand_path('./config/asteroid.rb')
|
@@ -8,7 +10,7 @@ if File.exists?(boot_file)
|
|
8
10
|
require boot_file
|
9
11
|
|
10
12
|
# Existing Application
|
11
|
-
Asteroid::Application.start ARGV
|
13
|
+
Asteroid::Application::CLI.start ARGV
|
12
14
|
|
13
15
|
else
|
14
16
|
# new application
|
data/lib/asteroid.rb
CHANGED
@@ -6,16 +6,17 @@ require 'yaml'
|
|
6
6
|
require 'digitalocean'
|
7
7
|
require 'aster'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
9
|
+
require 'asteroid/version'
|
10
|
+
require 'asteroid/version.rb'
|
11
|
+
require 'asteroid/provider.rb'
|
12
|
+
require 'asteroid/config.rb'
|
13
|
+
require 'asteroid/file_reference.rb'
|
14
|
+
require 'asteroid/script.rb'
|
15
|
+
require 'asteroid/server.rb'
|
16
|
+
require 'asteroid/ssh_key.rb'
|
17
|
+
require 'asteroid/key_reference.rb'
|
18
|
+
require 'asteroid/instance.rb'
|
19
|
+
require 'asteroid/template.rb'
|
19
20
|
|
20
21
|
module Asteroid
|
21
22
|
end
|
data/lib/asteroid/application.rb
CHANGED
@@ -1,19 +1,73 @@
|
|
1
1
|
require 'thor'
|
2
|
+
require 'thor/group'
|
2
3
|
|
3
4
|
require 'asteroid/generator'
|
4
5
|
|
5
6
|
module Asteroid
|
6
7
|
|
7
|
-
|
8
|
-
desc "instances [type]", "create a asteroid application at NAME"
|
9
|
-
option :type
|
10
|
-
def instances()
|
11
|
-
i = Instance.all
|
12
|
-
binding.pry
|
8
|
+
module Application
|
13
9
|
|
10
|
+
class Instance < Thor
|
11
|
+
desc "list", "create a asteroid application at NAME"
|
12
|
+
def list()
|
13
|
+
instances = Asteroid::Instance.all
|
14
|
+
instances.each do |instance|
|
15
|
+
puts [instance.id, instance.name, instance.server.provider.type].join("\t")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "ssh [instance-id]", "run the astroid command"
|
20
|
+
def ssh(i)
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "destroy COMMAND", "destroy the instance"
|
24
|
+
option :instance
|
25
|
+
def destroy(instance_id, *rest)
|
26
|
+
instance = Asteroid::Instance.find instance_id
|
27
|
+
instance.destroy
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "eval COMMAND", "run the astroid command"
|
31
|
+
option :instance
|
32
|
+
option :server, banner: '<server>'
|
33
|
+
def eval(instance_id, *rest)
|
34
|
+
instance = Asteroid::Instance.find instance_id
|
35
|
+
instance.eval_command rest.join(' ')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Server < Thor
|
40
|
+
desc "list", "list server configs"
|
41
|
+
def list
|
42
|
+
servers = Asteroid::Server.all
|
43
|
+
servers.each do |server|
|
44
|
+
puts [server.name, server.provider.type].join("\t")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
desc "create TYPE", "create an instance of a server"
|
49
|
+
def create(name)
|
50
|
+
server = Asteroid::Server.named name
|
51
|
+
if server
|
52
|
+
server.create_instance!
|
53
|
+
else
|
54
|
+
puts "Unknown server named #{name}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
class CLI < Thor
|
61
|
+
desc "instance SUBCOMMAND", "test in CLI"
|
62
|
+
subcommand "instance", Instance
|
63
|
+
|
64
|
+
desc "server SUBCOMMAND", "test in CLI"
|
65
|
+
subcommand "server", Server
|
14
66
|
end
|
67
|
+
|
15
68
|
end
|
16
69
|
|
70
|
+
|
17
71
|
class NewApplication < Thor
|
18
72
|
|
19
73
|
desc "new NAME", "create a asteroid application at NAME"
|
@@ -25,7 +79,6 @@ module Asteroid
|
|
25
79
|
generator.generate!
|
26
80
|
|
27
81
|
#puts "from: #{options[:from]}" if options[:from]
|
28
|
-
binding.pry
|
29
82
|
end
|
30
83
|
|
31
84
|
end
|
data/lib/asteroid/config.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
1
|
module Asteroid
|
2
2
|
|
3
|
-
def self.initialize!
|
4
|
-
if File.exists?(Config.initializer)
|
5
|
-
eval File.read(Config.initializer)
|
6
|
-
else
|
7
|
-
puts "No initializer"
|
8
|
-
end
|
9
|
-
end
|
10
3
|
|
11
4
|
def self.root=(root)
|
12
5
|
@root = root
|
@@ -20,6 +13,28 @@ module Asteroid
|
|
20
13
|
|
21
14
|
class << self
|
22
15
|
|
16
|
+
def boot!
|
17
|
+
if File.exists? self.secret_config_file
|
18
|
+
@secrets = YAML::load_file self.secret_config_file || {}
|
19
|
+
else
|
20
|
+
@secrets = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
# Load secret provider definition file
|
24
|
+
if File.exists?(Config.secret_provider_file)
|
25
|
+
eval File.read(Config.secret_provider_file)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Set search paths
|
29
|
+
Asteroid::FileReference.search_paths << Config.file_dir
|
30
|
+
Asteroid::FileReference.search_paths << Config.secret_file_dir
|
31
|
+
|
32
|
+
Asteroid::ScriptReference.search_paths << Config.script_dir
|
33
|
+
Asteroid::ScriptReference.search_paths << Config.secret_script_dir
|
34
|
+
|
35
|
+
Asteroid::KeyReference.search_paths << Config.secret_key_dir
|
36
|
+
end
|
37
|
+
|
23
38
|
def configure(root, options = {}, &block)
|
24
39
|
options = default_config(root)
|
25
40
|
options.merge! options
|
@@ -29,18 +44,17 @@ module Asteroid
|
|
29
44
|
|
30
45
|
yield self if block_given?
|
31
46
|
|
32
|
-
|
33
|
-
@secrets = YAML::load_file self.secret_config_file || {}
|
34
|
-
else
|
35
|
-
@secrets = {}
|
36
|
-
end
|
37
|
-
|
47
|
+
boot!
|
38
48
|
end
|
39
49
|
|
40
50
|
def secret
|
41
51
|
@secrets
|
42
52
|
end
|
43
53
|
|
54
|
+
def template_engines
|
55
|
+
@template_engines ||= {}
|
56
|
+
end
|
57
|
+
|
44
58
|
attr_accessor :asteroid_dir
|
45
59
|
attr_accessor :script_dir
|
46
60
|
attr_accessor :file_dir
|
@@ -59,7 +73,7 @@ module Asteroid
|
|
59
73
|
def default_config(root)
|
60
74
|
asteroid_dir = File.join(root, '/asteroid')
|
61
75
|
config_dir = File.join(root, '/config')
|
62
|
-
secret_dir = File.join(root, '/
|
76
|
+
secret_dir = File.join(root, '/secrets')
|
63
77
|
|
64
78
|
{
|
65
79
|
asteroid_dir: asteroid_dir,
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
module Asteroid
|
5
|
+
class FileReference
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def search_paths
|
9
|
+
@search_paths ||= []
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def path_is_absolute?(path)
|
16
|
+
Pathname.new(path).absolute?
|
17
|
+
end
|
18
|
+
|
19
|
+
public
|
20
|
+
|
21
|
+
attr_accessor :data
|
22
|
+
|
23
|
+
def initialize(fname)
|
24
|
+
if path_is_absolute?(fname)
|
25
|
+
@filename = fname
|
26
|
+
else
|
27
|
+
# Scan search paths looking for exact match
|
28
|
+
self.class.search_paths.each do |search|
|
29
|
+
break unless @filename.nil?
|
30
|
+
proposed_filename = File.join(search, fname)
|
31
|
+
if File.exists?(proposed_filename)
|
32
|
+
@filename = proposed_filename
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Scan search paths looking for partial match
|
37
|
+
self.class.search_paths.each do |search|
|
38
|
+
break unless @filename.nil?
|
39
|
+
glob = File.join(search, fname + "*")
|
40
|
+
matches = Dir[glob]
|
41
|
+
if matches.size == 1
|
42
|
+
@filename = matches.first
|
43
|
+
elsif matches.size > 1
|
44
|
+
raise "Ambiguous filename #{fname}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
if @filename.nil?
|
50
|
+
raise "Could not find file #{fname}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def name
|
55
|
+
File.basename @filename
|
56
|
+
end
|
57
|
+
|
58
|
+
def type
|
59
|
+
name.split('.').last.to_sym
|
60
|
+
end
|
61
|
+
|
62
|
+
def exists?
|
63
|
+
# should always be yes
|
64
|
+
File.exists?(@filename)
|
65
|
+
end
|
66
|
+
|
67
|
+
def template?
|
68
|
+
last = @filename.split('.').last
|
69
|
+
if last
|
70
|
+
Asteroid::Config.template_engines.keys.include?(last.to_sym)
|
71
|
+
else
|
72
|
+
false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def filename
|
77
|
+
@filename
|
78
|
+
end
|
79
|
+
|
80
|
+
def rendered_filename
|
81
|
+
if template?
|
82
|
+
@rendered_filename ||= begin
|
83
|
+
file = Tempfile.new('config')
|
84
|
+
file.write render
|
85
|
+
file.rewind
|
86
|
+
file.path
|
87
|
+
end
|
88
|
+
else
|
89
|
+
filename
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def render(extra = nil)
|
94
|
+
template_data = read
|
95
|
+
rendered_template = Template.new(:erb).render(
|
96
|
+
template_data,
|
97
|
+
data.merge(extra)
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
data/lib/asteroid/generator.rb
CHANGED
data/lib/asteroid/instance.rb
CHANGED
@@ -24,21 +24,41 @@ module Asteroid
|
|
24
24
|
|
25
25
|
attr_reader :server,
|
26
26
|
:provider,
|
27
|
-
:type
|
27
|
+
:type,
|
28
|
+
:id,
|
29
|
+
:name,
|
30
|
+
:ip_address
|
28
31
|
|
29
32
|
|
30
33
|
def initialize(options = {})
|
31
|
-
|
34
|
+
options = options.dup
|
35
|
+
|
36
|
+
o = options.dup
|
37
|
+
|
32
38
|
@server = options.delete :server
|
33
39
|
@type = options.delete :type
|
40
|
+
@id = options.delete :id
|
41
|
+
@name = options.delete :name
|
42
|
+
@ip_address = options.delete :ip_address
|
34
43
|
|
35
|
-
@
|
44
|
+
if @name && @type.nil?
|
45
|
+
@type = name.split('-').first.to_sym
|
46
|
+
end
|
47
|
+
|
48
|
+
if @server.nil? && @type.nil?
|
49
|
+
raise "Instance must have a server type :type attribute"
|
50
|
+
elsif @server.nil?
|
51
|
+
@server = Server.named @type
|
52
|
+
end
|
53
|
+
|
54
|
+
if @provider
|
36
55
|
|
37
|
-
|
38
|
-
|
39
|
-
|
56
|
+
end
|
57
|
+
|
58
|
+
@attributes = options
|
40
59
|
|
41
|
-
|
60
|
+
|
61
|
+
server.provider.required_instance_attributes.each do |att|
|
42
62
|
require_attribute att
|
43
63
|
end
|
44
64
|
|
@@ -84,7 +104,7 @@ module Asteroid
|
|
84
104
|
end
|
85
105
|
|
86
106
|
def self.find(id)
|
87
|
-
all.select{|i| i.id == id}.first
|
107
|
+
all.select{|i| i.id == id || i.id.to_s == id.to_s}.first
|
88
108
|
end
|
89
109
|
|
90
110
|
def env
|
@@ -98,7 +118,7 @@ module Asteroid
|
|
98
118
|
end
|
99
119
|
|
100
120
|
def destroy
|
101
|
-
|
121
|
+
server.provider.destroy_instance self
|
102
122
|
end
|
103
123
|
|
104
124
|
private
|