asteroid 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/asteroid.svg)](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
|