bosh_openstack_registry 0.0.1

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.
data/README ADDED
@@ -0,0 +1,3 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ BOSH OpenStack Registry
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ $:.unshift(File.expand_path("../../rake", __FILE__))
4
+
5
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __FILE__)
6
+
7
+ require "rubygems"
8
+ require "bundler"
9
+ Bundler.setup(:default, :test)
10
+
11
+ require "rake"
12
+ begin
13
+ require "rspec/core/rake_task"
14
+ rescue LoadError
15
+ end
16
+
17
+ require "bundler_task"
18
+ require "ci_task"
19
+
20
+ gem_helper = Bundler::GemHelper.new(Dir.pwd)
21
+
22
+ desc "Build OpenStack Registry gem into the pkg directory"
23
+ task "build" do
24
+ gem_helper.build_gem
25
+ end
26
+
27
+ desc "Build and install OpenStack Registry into system gems"
28
+ task "install" do
29
+ Rake::Task["bundler:install"].invoke
30
+ gem_helper.install_gem
31
+ end
32
+
33
+ BundlerTask.new
34
+
35
+ if defined?(RSpec)
36
+ namespace :spec do
37
+ desc "Run Unit Tests"
38
+ rspec_task = RSpec::Core::RakeTask.new(:unit) do |t|
39
+ t.pattern = "spec/unit/**/*_spec.rb"
40
+ t.rspec_opts = %w(--format progress --colour)
41
+ end
42
+
43
+ CiTask.new do |task|
44
+ task.rspec_task = rspec_task
45
+ end
46
+ end
47
+
48
+ desc "Run tests"
49
+ task :spec => %w(spec:unit)
50
+ end
data/bin/migrate ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
4
+
5
+ require "rubygems"
6
+ require "bundler/setup"
7
+ require "logger"
8
+ require "sequel"
9
+
10
+ $:.unshift(File.dirname(__FILE__) + "/../lib")
11
+
12
+ require "openstack_registry"
13
+
14
+ config_file = nil
15
+
16
+ opts = OptionParser.new do |opts|
17
+ opts.on("-c", "--config FILE", "configuration file") do |opt|
18
+ config_file = opt
19
+ end
20
+ end
21
+
22
+ opts.parse!(ARGV.dup)
23
+
24
+ if config_file.nil?
25
+ puts opts
26
+ exit 1
27
+ end
28
+
29
+ include Bosh::OpenstackRegistry::YamlHelper
30
+
31
+ config = load_yaml_file(config_file)
32
+
33
+ db = Bosh::OpenstackRegistry.connect_db(config["db"])
34
+ migrations_dir = File.expand_path("../../db/migrations", __FILE__)
35
+
36
+ options = {
37
+ :table => "openstack_registry_schema"
38
+ }
39
+
40
+ Sequel.extension :migration
41
+ Sequel::TimestampMigrator.run(db, migrations_dir, options)
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ gemfile = File.expand_path("../../Gemfile", __FILE__)
4
+
5
+ if File.exists?(gemfile)
6
+ ENV["BUNDLE_GEMFILE"] = gemfile
7
+ require "rubygems"
8
+ require "bundler/setup"
9
+ end
10
+
11
+ $:.unshift(File.expand_path("../../lib", __FILE__))
12
+
13
+ require "openstack_registry"
14
+ require "optparse"
15
+
16
+ config_file = nil
17
+
18
+ opts = OptionParser.new do |opts|
19
+ opts.on("-c", "--config FILE", "configuration file") do |opt|
20
+ config_file = opt
21
+ end
22
+ end
23
+
24
+ opts.parse!(ARGV.dup)
25
+
26
+ if config_file.nil?
27
+ puts opts
28
+ exit 1
29
+ end
30
+
31
+ runner = Bosh::OpenstackRegistry::Runner.new(config_file)
32
+
33
+ Signal.trap("INT") do
34
+ runner.stop
35
+ exit(1)
36
+ end
37
+
38
+ runner.run
@@ -0,0 +1,67 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::OpenstackRegistry
4
+
5
+ class ApiController < Sinatra::Base
6
+
7
+ not_found do
8
+ json(:status => "not_found")
9
+ end
10
+
11
+ error do
12
+ exception = request.env["sinatra.error"]
13
+ @logger.error(exception)
14
+ status(500)
15
+ json(:status => "error")
16
+ end
17
+
18
+ get "/servers/:server_id/settings" do
19
+ ip_check = authorized? ? nil : request.ip
20
+ settings = @server_manager.read_settings(params[:server_id])
21
+ json(:status => "ok", :settings => settings)
22
+ end
23
+
24
+ put "/servers/:server_id/settings" do
25
+ protected!
26
+ @server_manager.update_settings(params[:server_id], request.body.read)
27
+ json(:status => "ok")
28
+ end
29
+
30
+ delete "/servers/:server_id/settings" do
31
+ protected!
32
+ @server_manager.delete_settings(params[:server_id])
33
+ json(:status => "ok")
34
+ end
35
+
36
+ def initialize
37
+ super
38
+ @logger = Bosh::OpenstackRegistry.logger
39
+
40
+ @users = Set.new
41
+ @users << [Bosh::OpenstackRegistry.http_user,
42
+ Bosh::OpenstackRegistry.http_password]
43
+ @server_manager = ServerManager.new
44
+ end
45
+
46
+ def protected!
47
+ unless authorized?
48
+ headers("WWW-Authenticate" => 'Basic realm="OpenStack Registry"')
49
+ halt(401, json("status" => "access_denied"))
50
+ end
51
+ end
52
+
53
+ def authorized?
54
+ @auth ||= Rack::Auth::Basic::Request.new(request.env)
55
+ @auth.provided? &&
56
+ @auth.basic? &&
57
+ @auth.credentials &&
58
+ @users.include?(@auth.credentials)
59
+ end
60
+
61
+ def json(payload)
62
+ Yajl::Encoder.encode(payload)
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,81 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::OpenstackRegistry
4
+
5
+ class << self
6
+
7
+ attr_accessor :logger
8
+ attr_accessor :http_port
9
+ attr_accessor :http_user
10
+ attr_accessor :http_password
11
+ attr_accessor :db
12
+
13
+ attr_writer :openstack
14
+
15
+ def configure(config)
16
+ validate_config(config)
17
+
18
+ @logger ||= Logger.new(config["logfile"] || STDOUT)
19
+
20
+ if config["loglevel"].kind_of?(String)
21
+ @logger.level = Logger.const_get(config["loglevel"].upcase)
22
+ end
23
+
24
+ @http_port = config["http"]["port"]
25
+ @http_user = config["http"]["user"]
26
+ @http_password = config["http"]["password"]
27
+
28
+ @openstack_properties = config["openstack"]
29
+
30
+ @openstack_options = {
31
+ :provider => "OpenStack",
32
+ :openstack_auth_url => @openstack_properties["auth_url"],
33
+ :openstack_username => @openstack_properties["username"],
34
+ :openstack_api_key => @openstack_properties["api_key"],
35
+ :openstack_tenant => @openstack_properties["tenant"]
36
+ }
37
+
38
+ @db = connect_db(config["db"])
39
+ end
40
+
41
+ def openstack
42
+ openstack ||= Fog::Compute.new(@openstack_options)
43
+ end
44
+
45
+ def connect_db(db_config)
46
+ connection_options = {
47
+ :max_connections => db_config["max_connections"],
48
+ :pool_timeout => db_config["pool_timeout"]
49
+ }
50
+
51
+ db = Sequel.connect(db_config["database"], connection_options)
52
+ db.logger = @logger
53
+ db.sql_log_level = :debug
54
+ db
55
+ end
56
+
57
+ def validate_config(config)
58
+ unless config.is_a?(Hash)
59
+ raise ConfigError, "Invalid config format, Hash expected, " \
60
+ "#{config.class} given"
61
+ end
62
+
63
+ unless config.has_key?("http") && config["http"].is_a?(Hash)
64
+ raise ConfigError, "HTTP configuration is missing from " \
65
+ "config file"
66
+ end
67
+
68
+ unless config.has_key?("db") && config["db"].is_a?(Hash)
69
+ raise ConfigError, "Database configuration is missing from " \
70
+ "config file"
71
+ end
72
+
73
+ unless config.has_key?("openstack") && config["openstack"].is_a?(Hash)
74
+ raise ConfigError, "OpenStack configuration is missing from " \
75
+ "config file"
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ end
@@ -0,0 +1,20 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::OpenstackRegistry
4
+
5
+ class Error < StandardError
6
+ def self.code(code = 500)
7
+ define_method(:code) { code }
8
+ end
9
+ end
10
+
11
+ class FatalError < Error; end
12
+
13
+ class ConfigError < Error; end
14
+ class ConnectionError < Error; end
15
+
16
+ class OpenstackError < Error; end
17
+
18
+ class ServerError < Error; end
19
+ class ServerNotFound < Error; code(404); end
20
+ end
@@ -0,0 +1,12 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::OpenstackRegistry::Models
4
+ class OpenstackServer < Sequel::Model
5
+
6
+ def validate
7
+ validates_presence [:server_id, :settings]
8
+ validates_unique :server_id
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::OpenstackRegistry
4
+ module Models
5
+ end
6
+ end
7
+
8
+ require "openstack_registry/models/openstack_server"
@@ -0,0 +1,56 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::OpenstackRegistry
4
+ class Runner
5
+ include YamlHelper
6
+
7
+ def initialize(config_file)
8
+ Bosh::OpenstackRegistry.configure(load_yaml_file(config_file))
9
+
10
+ @logger = Bosh::OpenstackRegistry.logger
11
+ @http_port = Bosh::OpenstackRegistry.http_port
12
+ @http_user = Bosh::OpenstackRegistry.http_user
13
+ @http_password = Bosh::OpenstackRegistry.http_password
14
+ end
15
+
16
+ def run
17
+ @logger.info("BOSH OpenStack Registry starting...")
18
+ EM.kqueue if EM.kqueue?
19
+ EM.epoll if EM.epoll?
20
+
21
+ EM.error_handler { |e| handle_em_error(e) }
22
+
23
+ EM.run do
24
+ start_http_server
25
+ end
26
+ end
27
+
28
+ def stop
29
+ @logger.info("BOSH OpenStack Registry shutting down...")
30
+ @http_server.stop! if @http_server
31
+ EM.stop
32
+ end
33
+
34
+ def start_http_server
35
+ @logger.info "HTTP server is starting on port #{@http_port}..."
36
+ @http_server = Thin::Server.new("0.0.0.0", @http_port, :signals => false) do
37
+ Thin::Logging.silent = true
38
+ map "/" do
39
+ run Bosh::OpenstackRegistry::ApiController.new
40
+ end
41
+ end
42
+ @http_server.start!
43
+ end
44
+
45
+ private
46
+
47
+ def handle_em_error(e)
48
+ @logger.send(level, e.to_s)
49
+ if e.respond_to?(:backtrace) && e.backtrace.respond_to?(:join)
50
+ @logger.send(level, e.backtrace.join("\n"))
51
+ end
52
+ stop
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,52 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::OpenstackRegistry
4
+
5
+ class ServerManager
6
+
7
+ def initialize
8
+ @logger = Bosh::OpenstackRegistry.logger
9
+ @openstack = Bosh::OpenstackRegistry.openstack
10
+ end
11
+
12
+ ##
13
+ # Updates server settings
14
+ # @param [String] server_id OpenStack server id (server record
15
+ # will be created in DB if it doesn't already exist)
16
+ # @param [String] settings New settings for the server
17
+ def update_settings(server_id, settings)
18
+ params = {
19
+ :server_id => server_id
20
+ }
21
+
22
+ server = Models::OpenstackServer[params] || Models::OpenstackServer.new(params)
23
+ server.settings = settings
24
+ server.save
25
+ end
26
+
27
+ ##
28
+ # Reads server settings
29
+ # @param [String] server_id OpenStack server id
30
+ def read_settings(server_id)
31
+ get_server(server_id).settings
32
+ end
33
+
34
+ def delete_settings(server_id)
35
+ get_server(server_id).destroy
36
+ end
37
+
38
+ private
39
+
40
+ def get_server(server_id)
41
+ server = Models::OpenstackServer[:server_id => server_id]
42
+
43
+ if server.nil?
44
+ raise ServerNotFound, "Can't find server `#{server_id}'"
45
+ end
46
+
47
+ server
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,7 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh
4
+ module OpenstackRegistry
5
+ VERSION = "0.0.1"
6
+ end
7
+ end
@@ -0,0 +1,24 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::OpenstackRegistry
4
+ module YamlHelper
5
+
6
+ def load_yaml_file(path, expected_type = Hash)
7
+ unless File.exists?(path)
8
+ raise(ConfigError, "Cannot find file `#{path}'")
9
+ end
10
+
11
+ yaml = YAML.load_file(path)
12
+
13
+ if expected_type && !yaml.is_a?(expected_type)
14
+ raise ConfigError, "Incorrect file format in `#{path}', " \
15
+ "#{expected_type} expected"
16
+ end
17
+
18
+ yaml
19
+ rescue SystemCallError => e
20
+ raise ConfigError, "Cannot load YAML file at `#{path}': #{e}"
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh
4
+ module OpenstackRegistry
5
+ autoload :Models, "openstack_registry/models"
6
+ end
7
+ end
8
+
9
+ require "fog"
10
+ require "logger"
11
+ require "sequel"
12
+ require "sinatra/base"
13
+ require "thin"
14
+ require "yajl"
15
+
16
+ require "openstack_registry/yaml_helper"
17
+
18
+ require "openstack_registry/api_controller"
19
+ require "openstack_registry/config"
20
+ require "openstack_registry/errors"
21
+ require "openstack_registry/server_manager"
22
+ require "openstack_registry/runner"
23
+ require "openstack_registry/version"
24
+
25
+ Sequel::Model.plugin :validation_helpers
@@ -0,0 +1,18 @@
1
+ ---
2
+ loglevel: debug
3
+
4
+ http:
5
+ port: 25695
6
+ user: admin
7
+ password: admin
8
+
9
+ db:
10
+ database: "sqlite:///:memory:"
11
+ max_connections: 32
12
+ pool_timeout: 10
13
+
14
+ openstack:
15
+ auth_url: "http://127.0.0.1:5000/v2.0/tokens"
16
+ username: foo
17
+ api_key: bar
18
+ tenant: foo
@@ -0,0 +1,114 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ $:.unshift(File.expand_path("../../lib", __FILE__))
4
+
5
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
6
+
7
+ require "rubygems"
8
+ require "bundler"
9
+ Bundler.setup(:default, :test)
10
+
11
+ require "fileutils"
12
+ require "logger"
13
+ require "tmpdir"
14
+
15
+ require "rspec"
16
+ require "rack/test"
17
+
18
+ module SpecHelper
19
+ class << self
20
+ attr_accessor :logger
21
+ attr_accessor :temp_dir
22
+
23
+ def init
24
+ ENV["RACK_ENV"] = "test"
25
+ configure_logging
26
+ configure_temp_dir
27
+
28
+ require "openstack_registry"
29
+ init_database
30
+ end
31
+
32
+ def configure_logging
33
+ if ENV["DEBUG"]
34
+ @logger = Logger.new(STDOUT)
35
+ else
36
+ path = File.expand_path("../spec.log", __FILE__)
37
+ log_file = File.open(path, "w")
38
+ log_file.sync = true
39
+ @logger = Logger.new(log_file)
40
+ end
41
+ end
42
+
43
+ def configure_temp_dir
44
+ @temp_dir = Dir.mktmpdir
45
+ ENV["TMPDIR"] = @temp_dir
46
+ FileUtils.mkdir_p(@temp_dir)
47
+ at_exit { FileUtils.rm_rf(@temp_dir) }
48
+ end
49
+
50
+ def init_database
51
+ @migrations_dir = File.expand_path("../../db/migrations", __FILE__)
52
+
53
+ Sequel.extension :migration
54
+
55
+ @db = Sequel.sqlite(:database => nil, :max_connections => 32, :pool_timeout => 10)
56
+ @db.loggers << @logger
57
+ Bosh::OpenstackRegistry.db = @db
58
+
59
+ run_migrations
60
+ end
61
+
62
+ def run_migrations
63
+ Sequel::Migrator.apply(@db, @migrations_dir, nil)
64
+ end
65
+
66
+ def reset_database
67
+ @db.execute("PRAGMA foreign_keys = OFF")
68
+ @db.tables.each do |table|
69
+ @db.drop_table(table)
70
+ end
71
+ @db.execute("PRAGMA foreign_keys = ON")
72
+ end
73
+
74
+ def reset
75
+ reset_database
76
+ run_migrations
77
+
78
+ Bosh::OpenstackRegistry.db = @db
79
+ Bosh::OpenstackRegistry.logger = @logger
80
+ end
81
+ end
82
+ end
83
+
84
+ SpecHelper.init
85
+
86
+ def valid_config
87
+ {
88
+ "logfile" => nil,
89
+ "loglevel" => "debug",
90
+ "http" => {
91
+ "user" => "admin",
92
+ "password" => "admin",
93
+ "port" => 25777
94
+ },
95
+ "db" => {
96
+ "max_connections" => 433,
97
+ "pool_timeout" => 227,
98
+ "database" => "sqlite:///:memory:"
99
+ },
100
+ "openstack" => {
101
+ "auth_url" => "http://127.0.0.1:5000/v2.0/tokens",
102
+ "username" => "foo",
103
+ "api_key" => "bar",
104
+ "tenant" => "foo"
105
+ }
106
+ }
107
+ end
108
+
109
+ RSpec.configure do |rspec|
110
+ rspec.before(:each) do
111
+ SpecHelper.reset
112
+ Bosh::OpenstackRegistry.logger = Logger.new(StringIO.new)
113
+ end
114
+ end
@@ -0,0 +1,74 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ require File.expand_path("../../spec_helper", __FILE__)
4
+
5
+ describe Bosh::OpenstackRegistry::ApiController do
6
+
7
+ before(:each) do
8
+ Bosh::OpenstackRegistry.http_user = "admin"
9
+ Bosh::OpenstackRegistry.http_password = "admin"
10
+
11
+ @server_manager = mock("server manager")
12
+ Bosh::OpenstackRegistry::ServerManager.stub!(:new).and_return(@server_manager)
13
+
14
+ rack_mock = Rack::MockSession.new(Bosh::OpenstackRegistry::ApiController.new)
15
+ @session = Rack::Test::Session.new(rack_mock)
16
+ end
17
+
18
+ def expect_json_response(response, status, body)
19
+ response.status.should == status
20
+ Yajl::Parser.parse(response.body).should == body
21
+ end
22
+
23
+ it "returns settings for given OpenStack server (IP check)" do
24
+ @server_manager.should_receive(:read_settings).
25
+ with("foo").and_return("bar")
26
+
27
+ @session.get("/servers/foo/settings")
28
+
29
+ expect_json_response(@session.last_response, 200,
30
+ { "status" => "ok", "settings" => "bar" })
31
+ end
32
+
33
+ it "returns settings (authorized user, no IP check)" do
34
+ @server_manager.should_receive(:read_settings).
35
+ with("foo").and_return("bar")
36
+
37
+ @session.basic_authorize("admin", "admin")
38
+ @session.get("/servers/foo/settings")
39
+
40
+ expect_json_response(@session.last_response, 200,
41
+ { "status" => "ok", "settings" => "bar" })
42
+ end
43
+
44
+ it "updates settings" do
45
+ @session.put("/servers/foo/settings", {}, { :input => "bar" })
46
+ expect_json_response(@session.last_response, 401,
47
+ { "status" => "access_denied" })
48
+
49
+ @server_manager.should_receive(:update_settings).
50
+ with("foo", "bar").and_return(true)
51
+
52
+ @session.basic_authorize("admin", "admin")
53
+ @session.put("/servers/foo/settings", {}, { :input => "bar" })
54
+
55
+ expect_json_response(@session.last_response, 200,
56
+ { "status" => "ok" })
57
+ end
58
+
59
+ it "deletes settings" do
60
+ @session.delete("/servers/foo/settings")
61
+ expect_json_response(@session.last_response, 401,
62
+ { "status" => "access_denied" })
63
+
64
+ @server_manager.should_receive(:delete_settings).
65
+ with("foo").and_return(true)
66
+
67
+ @session.basic_authorize("admin", "admin")
68
+ @session.delete("/servers/foo/settings")
69
+
70
+ expect_json_response(@session.last_response, 200,
71
+ { "status" => "ok" })
72
+ end
73
+
74
+ end
@@ -0,0 +1,56 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ require File.expand_path("../../spec_helper", __FILE__)
4
+
5
+ describe Bosh::OpenstackRegistry do
6
+
7
+ describe "configuring OpenStack registry" do
8
+ it "reads provided configuration file and sets singletons" do
9
+ Bosh::OpenstackRegistry.configure(valid_config)
10
+
11
+ logger = Bosh::OpenstackRegistry.logger
12
+
13
+ logger.should be_kind_of(Logger)
14
+ logger.level.should == Logger::DEBUG
15
+
16
+ Bosh::OpenstackRegistry.http_port.should == 25777
17
+ Bosh::OpenstackRegistry.http_user.should == "admin"
18
+ Bosh::OpenstackRegistry.http_password.should == "admin"
19
+
20
+ db = Bosh::OpenstackRegistry.db
21
+ db.should be_kind_of(Sequel::SQLite::Database)
22
+ db.opts[:database].should == "/:memory:"
23
+ db.opts[:max_connections].should == 433
24
+ db.opts[:pool_timeout].should == 227
25
+ end
26
+
27
+ it "validates configuration file" do
28
+ expect {
29
+ Bosh::OpenstackRegistry.configure("foobar")
30
+ }.to raise_error(Bosh::OpenstackRegistry::ConfigError,
31
+ /Invalid config format/)
32
+
33
+ config = valid_config.merge("http" => nil)
34
+
35
+ expect {
36
+ Bosh::OpenstackRegistry.configure(config)
37
+ }.to raise_error(Bosh::OpenstackRegistry::ConfigError,
38
+ /HTTP configuration is missing/)
39
+
40
+ config = valid_config.merge("db" => nil)
41
+
42
+ expect {
43
+ Bosh::OpenstackRegistry.configure(config)
44
+ }.to raise_error(Bosh::OpenstackRegistry::ConfigError,
45
+ /Database configuration is missing/)
46
+
47
+ config = valid_config.merge("openstack" => nil)
48
+
49
+ expect {
50
+ Bosh::OpenstackRegistry.configure(config)
51
+ }.to raise_error(Bosh::OpenstackRegistry::ConfigError,
52
+ /OpenStack configuration is missing/)
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,82 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ require File.expand_path("../../spec_helper", __FILE__)
4
+
5
+ describe Bosh::OpenstackRegistry::Runner do
6
+
7
+ def make_runner(config_file)
8
+ Bosh::OpenstackRegistry::Runner.new(config_file)
9
+ end
10
+
11
+ def write_config(file, config)
12
+ File.open(file, "w") do |f|
13
+ YAML.dump(config, f)
14
+ end
15
+ end
16
+
17
+ describe "initializing" do
18
+ it "configures OpenStack registry using provided file" do
19
+ config_file = Tempfile.new("config")
20
+ config = { "key" => "value" }
21
+ write_config(config_file.path, config)
22
+
23
+ Bosh::OpenstackRegistry.should_receive(:configure).with(config)
24
+ make_runner(config_file.path)
25
+ end
26
+
27
+ it "fails if config file not found" do
28
+ expect {
29
+ make_runner("foo")
30
+ }.to raise_error(Bosh::OpenstackRegistry::ConfigError, "Cannot find file `foo'")
31
+ end
32
+
33
+ it "fails when config file has incorrect format" do
34
+ config_file = Tempfile.new("config")
35
+ config = "foo"
36
+ write_config(config_file.path, config)
37
+
38
+ expect {
39
+ make_runner(config_file.path)
40
+ }.to raise_error(Bosh::OpenstackRegistry::ConfigError, /Incorrect file format/)
41
+ end
42
+
43
+ it "fails when some syscall fails" do
44
+ config_file = Tempfile.new("config")
45
+ write_config(config_file.path, { "foo" => "bar" })
46
+
47
+ YAML.stub!(:load_file).and_raise(SystemCallError.new("baz"))
48
+
49
+ expect {
50
+ make_runner(config_file.path)
51
+ }.to raise_error(Bosh::OpenstackRegistry::ConfigError, /baz/)
52
+ end
53
+ end
54
+
55
+ describe "running/stopping" do
56
+ before(:each) do
57
+ @config_file = Tempfile.new("config")
58
+ write_config(@config_file.path, valid_config)
59
+ end
60
+
61
+ it "spins up/shuts down reactor and HTTP server" do
62
+ runner = make_runner(@config_file)
63
+ mock_thin = mock("thin")
64
+
65
+ EM.should_receive(:run).and_yield
66
+
67
+ Thin::Server.should_receive(:new).
68
+ with("0.0.0.0", 25777, :signals => false).
69
+ and_return(mock_thin)
70
+
71
+ mock_thin.should_receive(:start!)
72
+
73
+ runner.run
74
+
75
+ mock_thin.should_receive(:stop!)
76
+ EM.should_receive(:stop)
77
+
78
+ runner.stop
79
+ end
80
+ end
81
+
82
+ end
@@ -0,0 +1,69 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ require File.expand_path("../../spec_helper", __FILE__)
4
+
5
+ describe Bosh::OpenstackRegistry::ServerManager do
6
+
7
+ before(:each) do
8
+ openstack = double(Fog::Compute)
9
+ Fog::Compute.stub(:new).and_return(openstack)
10
+ @openstack = mock("openstack")
11
+ Bosh::OpenstackRegistry.openstack = @openstack
12
+ end
13
+
14
+ let(:manager) do
15
+ Bosh::OpenstackRegistry::ServerManager.new
16
+ end
17
+
18
+ def create_server(params)
19
+ Bosh::OpenstackRegistry::Models::OpenstackServer.create(params)
20
+ end
21
+
22
+ describe "reading settings" do
23
+ it "returns settings" do
24
+ create_server(:server_id => "foo", :settings => "bar")
25
+ manager.read_settings("foo").should == "bar"
26
+ end
27
+
28
+ it "raises an error if server not found" do
29
+ expect {
30
+ manager.read_settings("foo")
31
+ }.to raise_error(Bosh::OpenstackRegistry::ServerNotFound,
32
+ "Can't find server `foo'")
33
+ end
34
+ end
35
+
36
+ describe "updating settings" do
37
+ it "updates settings (new server)" do
38
+ manager.update_settings("foo", "baz")
39
+ manager.read_settings("foo").should == "baz"
40
+ end
41
+
42
+ it "updates settings (existing server)" do
43
+ create_server(:server_id => "foo", :settings => "bar")
44
+ manager.read_settings("foo").should == "bar"
45
+ manager.update_settings("foo", "baz")
46
+ manager.read_settings("foo").should == "baz"
47
+ end
48
+ end
49
+
50
+ describe "deleting settings" do
51
+ it "deletes settings" do
52
+ manager.update_settings("foo", "baz")
53
+ manager.delete_settings("foo")
54
+
55
+ expect {
56
+ manager.read_settings("foo")
57
+ }.to raise_error(Bosh::OpenstackRegistry::ServerNotFound,
58
+ "Can't find server `foo'")
59
+ end
60
+
61
+ it "raises an error if server not found" do
62
+ expect {
63
+ manager.delete_settings("foo")
64
+ }.to raise_error(Bosh::OpenstackRegistry::ServerNotFound,
65
+ "Can't find server `foo'")
66
+ end
67
+ end
68
+
69
+ end
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bosh_openstack_registry
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - VMware
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sequel
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: sinatra
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: thin
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: yajl-ruby
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: fog
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 1.4.0
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 1.4.0
94
+ description: BOSH OpenStack registry
95
+ email: support@vmware.com
96
+ executables:
97
+ - openstack_registry
98
+ extensions: []
99
+ extra_rdoc_files: []
100
+ files:
101
+ - bin/migrate
102
+ - bin/openstack_registry
103
+ - lib/openstack_registry.rb
104
+ - lib/openstack_registry/api_controller.rb
105
+ - lib/openstack_registry/config.rb
106
+ - lib/openstack_registry/errors.rb
107
+ - lib/openstack_registry/models.rb
108
+ - lib/openstack_registry/models/openstack_server.rb
109
+ - lib/openstack_registry/runner.rb
110
+ - lib/openstack_registry/server_manager.rb
111
+ - lib/openstack_registry/version.rb
112
+ - lib/openstack_registry/yaml_helper.rb
113
+ - README
114
+ - Rakefile
115
+ - spec/assets/sample_config.yml
116
+ - spec/spec_helper.rb
117
+ - spec/unit/api_controller_spec.rb
118
+ - spec/unit/config_spec.rb
119
+ - spec/unit/runner_spec.rb
120
+ - spec/unit/server_manager_spec.rb
121
+ homepage: http://www.vmware.com
122
+ licenses: []
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ! '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ segments:
134
+ - 0
135
+ hash: -1851942175393583791
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ segments:
143
+ - 0
144
+ hash: -1851942175393583791
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 1.8.24
148
+ signing_key:
149
+ specification_version: 3
150
+ summary: BOSH OpenStack registry
151
+ test_files:
152
+ - spec/assets/sample_config.yml
153
+ - spec/spec_helper.rb
154
+ - spec/unit/api_controller_spec.rb
155
+ - spec/unit/config_spec.rb
156
+ - spec/unit/runner_spec.rb
157
+ - spec/unit/server_manager_spec.rb