asteroid 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/Gemfile +1 -0
  4. data/README.md +45 -4
  5. data/Rakefile +1 -0
  6. data/asteroid.gemspec +0 -1
  7. data/bin/asteroid +4 -2
  8. data/lib/asteroid.rb +11 -10
  9. data/lib/asteroid/application.rb +60 -7
  10. data/lib/asteroid/config.rb +28 -14
  11. data/lib/asteroid/file_reference.rb +102 -0
  12. data/lib/asteroid/generator.rb +0 -4
  13. data/lib/asteroid/instance.rb +29 -9
  14. data/lib/asteroid/instance/command.rb +71 -36
  15. data/lib/asteroid/instance/scp.rb +26 -0
  16. data/lib/asteroid/instance/ssh.rb +2 -1
  17. data/lib/asteroid/instance/vars.rb +5 -2
  18. data/lib/asteroid/key_reference.rb +45 -0
  19. data/lib/asteroid/provider/abstract.rb +16 -1
  20. data/lib/asteroid/provider/digital_ocean.rb +35 -6
  21. data/lib/asteroid/provider/mock.rb +36 -14
  22. data/lib/asteroid/script.rb +3 -57
  23. data/lib/asteroid/server.rb +44 -25
  24. data/lib/asteroid/template.rb +19 -7
  25. data/lib/asteroid/template/liquid.rb +0 -0
  26. data/lib/asteroid/version.rb +1 -1
  27. data/sample/.gitignore +2 -0
  28. data/sample/README.md +1 -0
  29. data/sample/Rakefile +0 -0
  30. data/sample/TODO +9 -0
  31. data/sample/asteroid/files/nginx/available_site.conf.erb +0 -0
  32. data/sample/asteroid/files/nginx/nginx.conf +1 -0
  33. data/sample/asteroid/scripts/ubuntu.aster +4 -0
  34. data/sample/asteroid/servers/default.yml +3 -0
  35. data/sample/asteroid/servers/web.yml +5 -0
  36. data/sample/config/asteroid.rb +9 -0
  37. data/test/helper.rb +18 -2
  38. data/test/unit/test_application.rb +17 -0
  39. data/test/unit/test_file_reference.rb +18 -0
  40. data/test/unit/test_instance.rb +20 -4
  41. data/test/unit/test_script_reference.rb +9 -0
  42. data/test/unit/test_server.rb +46 -2
  43. data/test/unit/test_template.rb +16 -0
  44. metadata +24 -17
  45. data/lib/asteroid/config_file.rb +0 -46
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d3ce3e8c2c0efe5635f743569fa70a6cc709b52e
4
- data.tar.gz: 1f50a63fb78232511d1765201d82eb5225e7b682
3
+ metadata.gz: e5c5cc037af98984058dd5b4f265e016566f8f3f
4
+ data.tar.gz: f63bd8fd4eb00c4ae7fc2b081c6c132ff8910040
5
5
  SHA512:
6
- metadata.gz: 916902671568e85392e6faac6ee8cc499013360377a47e0cf9ebac7751902394f5a6f9e338a255e80abde8456a753b5ddb6e197ae27bae6b28fd856f4cda18e2
7
- data.tar.gz: d3656731753ee60ac60a2f8bbdb779d2fb7baca091e53370b22adf8a9a5ec2fc9dbe16ae43ee9f3676d8e0b03b8e995153022136342fb1db65cbfc6cc72eb4a3
6
+ metadata.gz: 5b3a7534a6668e92a89ac8c605502017e5bbafe4fa930a856bfc5e6c037bae2eedcd7fe83bbc4c92482bdfd83df1ffb9aa536d656f76b55dbe7912e1d0d3d27d
7
+ data.tar.gz: 3d79c608d88e060845516c5424bd1374d04769014acec7961a701ca64de60274c8ce061cb0d6e080776c29f0476556e1710d879345ed680ce90801fcf19a0d20
@@ -0,0 +1,2 @@
1
+ language: ruby
2
+ script: "bundle exec rake test"
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ # gem "aster", path: "/Users/sam/Documents/Projects/aster"
3
4
  # Specify your gem's dependencies in asteroid.gemspec
4
5
  gemspec
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
- gem install asteroid
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
@@ -4,6 +4,7 @@ require "bundler/gem_tasks"
4
4
  task :default => :test
5
5
 
6
6
  require 'rake/testtask'
7
+
7
8
  Rake::TestTask.new(:test) do |test|
8
9
  test.libs << 'lib' << 'test' << '.'
9
10
  test.pattern = 'test/**/test_*.rb'
@@ -29,5 +29,4 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency "rake"
30
30
  spec.add_development_dependency "pry"
31
31
  spec.add_development_dependency "minitest"
32
- spec.add_development_dependency "autotest"
33
32
  end
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require_relative '../lib/asteroid'
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
@@ -6,16 +6,17 @@ require 'yaml'
6
6
  require 'digitalocean'
7
7
  require 'aster'
8
8
 
9
-
10
- require_relative './asteroid/version.rb'
11
- require_relative './asteroid/provider.rb'
12
- require_relative './asteroid/config.rb'
13
- require_relative './asteroid/script.rb'
14
- require_relative './asteroid/config_file.rb'
15
- require_relative './asteroid/server.rb'
16
- require_relative './asteroid/ssh_key.rb'
17
- require_relative './asteroid/instance.rb'
18
- require_relative './asteroid/template.rb'
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
@@ -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
- class Application < Thor
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
@@ -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
- if File.exists? self.secret_config_file
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, '/sercrets')
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
@@ -53,10 +53,6 @@ module Asteroid
53
53
 
54
54
  mkdir c[:secret_key_dir]
55
55
  touch File.join(c[:secret_key_dir], '.keep')
56
-
57
-
58
- binding.pry
59
-
60
56
  end
61
57
 
62
58
 
@@ -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
- @provider = options.delete :provider
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
- @attributes = options
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
- # Validate Attributes
38
- require_attribute :name
39
- require_attribute :id
56
+ end
57
+
58
+ @attributes = options
40
59
 
41
- provider.required_instance_attributes.each do |att|
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
- @provider.destroy_instance self
121
+ server.provider.destroy_instance self
102
122
  end
103
123
 
104
124
  private