vagrant-rancher 1.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 07fc0ab4dffdade295fb36426c3e1a7b6979763c
4
+ data.tar.gz: 7f8c27bd89e8c65c707282b8a28b10e9d4f8bd4b
5
+ SHA512:
6
+ metadata.gz: 0b7d6c32011364096681eced5929074fa3d7dcf03e856066a7d2dc09e5c2673f4b57c92660a8f18c286cae0802c6ad5bca51e5e3ca579a2f7e6e9691a7de05e2
7
+ data.tar.gz: d01d57d525a84e44a34e519090a6d6f64b26692fe3c95f2c970d24e5f75b2dfd485ad190207c8f2676c57027204c9743e1831f42f695665231bd67ceaf8abdd4
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .vagrant
19
+ *.swp
data/.rubocop.yml ADDED
@@ -0,0 +1,11 @@
1
+ AllCops:
2
+ Include:
3
+ - 'Rakefile'
4
+ - 'lib/**'
5
+ - '*.gemspec'
6
+
7
+ Metrics/LineLength:
8
+ Enabled: false
9
+
10
+ Documentation:
11
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development do
4
+ gem 'vagrant', git: 'https://github.com/mitchellh/vagrant.git'
5
+ gem 'rubocop', require: false
6
+ end
7
+
8
+ group :plugins do
9
+ gem 'vagrant-rancher', path: '.'
10
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 nextrevision
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # vagrant-rancher
2
+
3
+ Vagrant plugin to install a Rancher server and agents on all vagrant guests.
4
+
5
+ ## Installation
6
+
7
+ ```
8
+ vagrant plugin install vagrant-rancher
9
+ ```
10
+
11
+ ## Requirements
12
+
13
+ * Docker to be intalled and running on the guest (ideally via unix socket)
14
+ * Guest to have an IP reachable by the host running the `vagrant` command (for VirtualBox and VMWare, see [private_network](https://www.vagrantup.com/docs/networking/private_network.html))
15
+
16
+ ## Usage
17
+
18
+ ```
19
+ Vagrant.configure("2") do |config|
20
+ config.vm.box = "ubuntu/trusty64"
21
+ config.vm.network "private_network", ip: "192.168.33.100"
22
+ config.vm.provider "virtualbox" do |vb|
23
+ vb.memory = "1024"
24
+ end
25
+
26
+ config.vm.provision :docker
27
+ config.vm.provision "rancher" do |rancher|
28
+ rancher.hostname = "192.168.33.100"
29
+ end
30
+ end
31
+ ```
32
+
33
+ The `vagrant-rancher` plugin requires the hostname being set to either a DNS name or IP that is reachable by the host running the `vagrant` command.
34
+
35
+ ### Options
36
+
37
+ * `hostname` (**required**): the DNS name or IP of the rancher server (must be reachable by the host running the `vagrant` command)
38
+ * `role` (*optional*, default: `'server'`): either 'server' (to run the Rancher server) or 'agent' to only run the Rancher agent
39
+ * `version` (*optional*, default: `'latest'`): version (tag) of the Rancher server container to run
40
+ * `port` (*optional*, default: `8080`): port to run the rancher server on in the case of the server, and communicate with in the case of the agent
41
+ * `server_args` (*optional*, default: `''`): additional args to pass to the Docker run command when starting the Rancher server
42
+ * `labels` (*optional*, default: `[]`): array of key=value pairs of labels to assign to the agent (ex. ["role=server","env=local"])
43
+ * `deactivate` (*optional*, default: `false`): deactivate the host in Rancher to prevent it from being scheduled on
44
+
45
+ ## Examples
46
+
47
+ See examples directory. For a quick setup of a Rancher environment running on RancherOS, see [https://github.com/nextrevision/rancheros-vagrant](https://github.com/nextrevision/rancheros-vagrant).
48
+
49
+ ## Providers Tested
50
+
51
+ * VirtualBox
52
+
53
+ ## Contributing
54
+
55
+ Bug reports and pull requests are welcome on GitHub at https://github.com/nextrevision/vagrant-rancher.
56
+
57
+ ## License
58
+
59
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
60
+
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rubocop/rake_task'
4
+
5
+ # Immediately sync all stdout so that tools like buildbot can
6
+ # immediately load in the output.
7
+ $stdout.sync = true
8
+ $stderr.sync = true
9
+
10
+ # Change to the directory of this file.
11
+ Dir.chdir(File.expand_path('../', __FILE__))
12
+
13
+ # This installs the tasks that help with gem creation and
14
+ # publishing.
15
+ Bundler::GemHelper.install_tasks
16
+
17
+ RuboCop::RakeTask.new
@@ -0,0 +1,50 @@
1
+ Vagrant.configure(2) do |config|
2
+ # start with a standard box
3
+ config.vm.box = "ubuntu/trusty64"
4
+
5
+ # in order to communicate with the api, we need to set
6
+ # a static, private ip address. this also allows for
7
+ # other vagrant guests to run agents and connect to the
8
+ # rancher server.
9
+ config.vm.network "private_network", ip: "192.168.33.100"
10
+
11
+ # increase the ram allotment to accomodate rancher
12
+ config.vm.provider "virtualbox" do |vb|
13
+ vb.memory = "1024"
14
+ end
15
+
16
+ # install docker on the guest
17
+ config.vm.provision :docker
18
+
19
+ # start the rancher server and agent
20
+ config.vm.provision :rancher do |rancher|
21
+ # the role to assign to the guest. can be either
22
+ # 'server' or 'agent', and 'server' implies 'agent'
23
+ # as well
24
+ rancher.role = "server"
25
+
26
+ # required parameter that instructs the provisioner
27
+ # how to reach the rancher server api endpoint
28
+ rancher.hostname = "192.168.33.100"
29
+
30
+ # port to run rancher server on and also connect over
31
+ # for agent communication
32
+ rancher.port = 8080
33
+
34
+ # version (tag) of the rancher server to deploy
35
+ rancher.version = "v0.63.1"
36
+
37
+ # do not deactivate the host, resulting in it not
38
+ # being scheduled upon (useful when you want the server
39
+ # to be the only container running on a guest)
40
+ rancher.deactivate = false
41
+
42
+ # additional args to pass to docker when starting
43
+ # the server
44
+ rancher.server_args = "--restart always"
45
+
46
+ # labels to assign to the agent and resulting host
47
+ # in rancher
48
+ rancher.labels = ["environment=local"]
49
+ end
50
+ end
@@ -0,0 +1,42 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ # required for setting the guest capabilities
5
+ require_relative 'vagrant_rancheros_guest_plugin.rb'
6
+
7
+ Vagrant.configure(2) do |config|
8
+ # global config settings
9
+ config.vm.box = "rancherio/rancheros"
10
+ config.vm.box_version = ">=0.4.1"
11
+ config.vm.synced_folder ".", "/vagrant", disabled: true
12
+
13
+ # define the rancher-server guest
14
+ config.vm.define "rancher-server" do |node|
15
+ node.vm.hostname = "rancher-server"
16
+ node.vm.network "private_network", ip: "192.168.33.100"
17
+ node.vm.provider "virtualbox" do |vb|
18
+ vb.memory = 1536
19
+ end
20
+
21
+ node.vm.provision :rancher do |rancher|
22
+ rancher.hostname = "192.168.33.100"
23
+ rancher.deactivate = true
24
+ rancher.labels = ["role=server"]
25
+ end
26
+ end
27
+
28
+ # define the rancher-agent guest
29
+ config.vm.define "rancher-agent" do |node|
30
+ node.vm.hostname = "rancher-agent"
31
+ node.vm.network "private_network", ip: "192.168.33.101"
32
+ node.vm.provider "virtualbox" do |vb|
33
+ vb.memory = 512
34
+ end
35
+
36
+ node.vm.provision :rancher do |rancher|
37
+ rancher.role = "agent"
38
+ rancher.hostname = "192.168.33.100"
39
+ rancher.labels = ["role=agent"]
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,74 @@
1
+ require 'ipaddr'
2
+
3
+ ## Hacking this until we get a real plugin
4
+
5
+ # Borrowing from http://stackoverflow.com/questions/1825928/netmask-to-cidr-in-ruby
6
+ IPAddr.class_eval do
7
+ def to_cidr
8
+ self.to_i.to_s(2).count("1")
9
+ end
10
+ end
11
+
12
+ module VagrantPlugins
13
+ module GuestLinux
14
+ class Plugin < Vagrant.plugin("2")
15
+ guest_capability("linux", "change_host_name") do
16
+ Cap::ChangeHostName
17
+ end
18
+
19
+ guest_capability("linux", "configure_networks") do
20
+ Cap::ConfigureNetworks
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ module VagrantPlugins
27
+ module GuestLinux
28
+ module Cap
29
+ class ConfigureNetworks
30
+ def self.configure_networks(machine, networks)
31
+ machine.communicate.tap do |comm|
32
+ interfaces = []
33
+ comm.sudo("ip link show|grep eth[1-9]|awk '{print $2}'|sed -e 's/:$//'") do |_, result|
34
+ interfaces = result.split("\n")
35
+ end
36
+
37
+ networks.each do |network|
38
+ dhcp = "true"
39
+ iface = interfaces[network[:interface].to_i - 1]
40
+
41
+ if network[:type] == :static
42
+ cidr = IPAddr.new(network[:netmask]).to_cidr
43
+ comm.sudo("ros config set rancher.network.interfaces.#{iface}.address #{network[:ip]}/#{cidr}")
44
+ comm.sudo("ros config set rancher.network.interfaces.#{iface}.match #{iface}")
45
+
46
+ dhcp = "false"
47
+ end
48
+ comm.sudo("ros config set rancher.network.interfaces.#{iface}.dhcp #{dhcp}")
49
+ end
50
+
51
+ comm.sudo("system-docker restart network")
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ module VagrantPlugins
60
+ module GuestLinux
61
+ module Cap
62
+ class ChangeHostName
63
+ def self.change_host_name(machine, name)
64
+ machine.communicate.tap do |comm|
65
+ if !comm.test("sudo hostname --fqdn | grep '#{name}'")
66
+ comm.sudo("hostname #{name.split('.')[0]}")
67
+ comm.sudo("echo '#{name.split('.')[0]}' > /etc/hostname")
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,12 @@
1
+ module VagrantPlugins
2
+ module Rancher
3
+ lib_path = Pathname.new(File.expand_path('../vagrant-rancher', __FILE__))
4
+ autoload :Errors, lib_path.join('errors')
5
+
6
+ def self.source_root
7
+ @source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
8
+ end
9
+ end
10
+ end
11
+
12
+ require 'vagrant-rancher/plugin'
@@ -0,0 +1,67 @@
1
+ module VagrantPlugins
2
+ module Rancher
3
+ class Config < Vagrant.plugin('2', :config)
4
+ attr_accessor :role
5
+ attr_accessor :version
6
+ attr_accessor :hostname
7
+ attr_accessor :port
8
+ attr_accessor :deactivate
9
+ attr_accessor :server_args
10
+ attr_accessor :labels
11
+
12
+ def initialize
13
+ @role = UNSET_VALUE
14
+ @version = UNSET_VALUE
15
+ @hostname = UNSET_VALUE
16
+ @port = UNSET_VALUE
17
+ @server_args = UNSET_VALUE
18
+ @labels = UNSET_VALUE
19
+ @deactivate = UNSET_VALUE
20
+ end
21
+
22
+ def finalize!
23
+ @role = 'server' if @role == UNSET_VALUE
24
+ @version = 'latest' if @version == UNSET_VALUE
25
+ @hostname = nil if @hostname == UNSET_VALUE
26
+ @port = 8080 if @port == UNSET_VALUE
27
+ @server_args = nil if @server_args == UNSET_VALUE
28
+ @labels = nil if @labels == UNSET_VALUE
29
+ @deactivate = false if @deactivate == UNSET_VALUE
30
+ end
31
+
32
+ def validate(_machine)
33
+ errors = _detected_errors
34
+
35
+ unless role == 'server' || role == 'agent'
36
+ errors << ':rancher provisioner requires role to either be "server" or "agent"'
37
+ end
38
+
39
+ unless version.is_a?(String) || version.nil?
40
+ errors << ':rancher provisioner requires version to be a string'
41
+ end
42
+
43
+ unless hostname.is_a?(String)
44
+ errors << ':rancher provisioner requires hostname to be set to a string'
45
+ end
46
+
47
+ unless port.is_a?(Fixnum) || port.is_a?(Fixnum)
48
+ errors << ':rancher provisioner requires port to be a number'
49
+ end
50
+
51
+ unless server_args.is_a?(String) || server_args.nil?
52
+ errors << ':rancher provisioner requires server_args to be a string'
53
+ end
54
+
55
+ unless labels.is_a?(Array) || labels.nil?
56
+ errors << ':rancher provisioner requires labels to be an array'
57
+ end
58
+
59
+ unless deactivate.is_a?(TrueClass) || deactivate.is_a?(FalseClass)
60
+ errors << ':rancher provisioner requires deactivate to be a bool'
61
+ end
62
+
63
+ { 'rancher provisioner' => errors }
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,49 @@
1
+ module VagrantPlugins
2
+ module Rancher
3
+ module Errors
4
+ class VagrantRancherError < Vagrant::Errors::VagrantError
5
+ error_namespace("vagrant_rancher.errors")
6
+ end
7
+
8
+ class DockerConnection < VagrantRancherError
9
+ error_key(:docker_connection)
10
+ end
11
+
12
+ class RancherServerContainer < VagrantRancherError
13
+ error_key(:rancher_server_container)
14
+ end
15
+
16
+ class RancherAgentContainer < VagrantRancherError
17
+ error_key(:rancher_agent_container)
18
+ end
19
+
20
+ class RegistrationTokenMissing < VagrantRancherError
21
+ error_key(:registration_token_missing)
22
+ end
23
+
24
+ class ApiConnectionError < VagrantRancherError
25
+ error_key(:api_connection_error)
26
+ end
27
+
28
+ class ApiConnectionTimeout < VagrantRancherError
29
+ error_key(:api_connection_timeout)
30
+ end
31
+
32
+ class AgentRegistrationTimeout < VagrantRancherError
33
+ error_key(:agent_registration_timeout)
34
+ end
35
+
36
+ class HttpResponseCode < VagrantRancherError
37
+ error_key(:http_response_code)
38
+ end
39
+
40
+ class ProjectNotFound < VagrantRancherError
41
+ error_key(:project_not_found)
42
+ end
43
+
44
+ class HostNotFound < VagrantRancherError
45
+ error_key(:host_not_found)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'vagrant'
3
+ rescue LoadError
4
+ raise 'The vagrant-rancher plugin must be run within Vagrant.'
5
+ end
6
+
7
+ module VagrantPlugins
8
+ module Rancher
9
+ class Plugin < Vagrant.plugin('2')
10
+ name 'vagrant-rancher'
11
+ description <<-DESC.gsub(/^ +/, '')
12
+ Vagrant plugin to install a Rancher server
13
+ and agents on all Vagrant guests.
14
+ DESC
15
+
16
+ action_hook(:init_i18n, :environment_load) { init_i18n }
17
+
18
+ config(:rancher, :provisioner) do
19
+ require_relative 'config'
20
+ Config
21
+ end
22
+
23
+ provisioner(:rancher) do
24
+ require_relative 'provisioner'
25
+ Provisioner
26
+ end
27
+
28
+ def self.init_i18n
29
+ I18n.load_path << File.expand_path("locales/en.yml", Rancher.source_root)
30
+ I18n.reload!
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,148 @@
1
+ require_relative 'rancher'
2
+ require_relative 'errors'
3
+
4
+ module VagrantPlugins
5
+ module Rancher
6
+ class Provisioner < Vagrant.plugin('2', :provisioner)
7
+ def initialize(machine, config, rancher = nil)
8
+ super(machine, config)
9
+ @rancher = rancher || RancherClient.new(@config.hostname, @config.port)
10
+ end
11
+
12
+ def provision
13
+ self.check_docker
14
+
15
+ if config.role == 'server'
16
+ self.install_server
17
+ self.configure_server
18
+ end
19
+
20
+ if config.role == 'server' || config.role == 'agent'
21
+ self.install_agent
22
+ self.configure_agent
23
+ end
24
+ end
25
+
26
+ # determines if we can reach the docker daemon
27
+ def check_docker
28
+ unless @machine.communicate.test('sh -c sleep 3; sudo docker info')
29
+ @machine.ui.error 'Could not connect to docker daemon'
30
+ raise Errors::DockerConnection
31
+ end
32
+ end
33
+
34
+ # installs the rancher server at the supplied version
35
+ def install_server
36
+ # check to see if the rancher server is already running
37
+ unless @machine.communicate.test('sudo docker inspect rancher-server')
38
+ @machine.ui.info "Starting server container: rancher/server:#{config.version}..."
39
+
40
+ docker_cmd = "docker run -d -t --name rancher-server -p #{@config.port}:8080"
41
+
42
+ # add any user supplied args to the docker command
43
+ unless config.server_args.nil?
44
+ docker_cmd = "#{docker_cmd} #{config.server_args}"
45
+ end
46
+
47
+ # start the server and error if there is a failure
48
+ unless @machine.communicate.sudo("#{docker_cmd} rancher/server:#{config.version}")
49
+ @machine.ui.error 'Could not start Rancher server container'
50
+ raise Errors::RancherServerContainer
51
+ end
52
+
53
+ # wait for the server api to come online
54
+ @machine.ui.detail 'Waiting for server API to become available...'
55
+ unless @rancher.wait_for_api
56
+ raise Errors::ApiConnectionTimeout,
57
+ :host => @config.hostname,
58
+ :port => @config.port
59
+ end
60
+
61
+ # gratuitous pause for the server api
62
+ sleep 5
63
+ end
64
+ end
65
+
66
+ # configures a running server with the required settings
67
+ def configure_server
68
+ # retrieve the default project id
69
+ project_id = @rancher.get_project_id
70
+ raise Errors::ProjectNotFound if project_id.nil?
71
+
72
+ # attempt to retrieve a registration token, otherwise create one
73
+ unless @rancher.get_registration_token project_id
74
+ @machine.ui.detail "Registration tokens have not been created, creating now..."
75
+ @rancher.create_registration_token project_id
76
+
77
+ # set the api.host setting required for agents
78
+ @rancher.configure_setting 'api.host', "http://#{@config.hostname}:#{@config.port}"
79
+ sleep(2)
80
+
81
+ # verify that the registration token was created
82
+ raise Errors::RegistrationTokenMissing unless @rancher.get_registration_token project_id
83
+ end
84
+ end
85
+
86
+ # runs the agent container on the guest
87
+ def install_agent
88
+ # if the agent container is not running, start it
89
+ unless @machine.communicate.test('sudo docker inspect rancher-agent')
90
+ # retrieve the default project id
91
+ project_id = @rancher.get_project_id
92
+ raise Errors::ProjectNotFound if project_id.nil?
93
+
94
+ # retrieve the registration token
95
+ @machine.ui.detail 'Retrieving agent registration command...'
96
+ registration_token = @rancher.get_registration_token project_id
97
+ raise Errors::RegistrationTokenMissing if registration_token.nil?
98
+
99
+ docker_cmd = registration_token['command']
100
+
101
+ # apply a default label with the machine id used for
102
+ # checking that the agent has indeed registered the host
103
+ labels = "id=#{@machine.id}"
104
+ # apply and additional host labels
105
+ unless config.labels.nil?
106
+ labels = "#{labels}&#{config.labels.join('&')}"
107
+ end
108
+
109
+ extra_args = "-e 'CATTLE_HOST_LABELS=#{labels}' --name rancher-agent-bootstrap"
110
+ docker_cmd = docker_cmd.sub('docker run', "docker run #{extra_args}")
111
+
112
+ # start the agent container
113
+ @machine.ui.info "Starting agent container: #{registration_token['image']}..."
114
+ unless @machine.communicate.sudo(docker_cmd)
115
+ @machine.ui.error 'Could not start Rancher agent container'
116
+ raise Errors::RancherAgentContainer
117
+ end
118
+
119
+ # wait for the agent to register the host in rancher (checks
120
+ # for the @machine.id in the host labels)
121
+ @machine.ui.detail 'Waiting for agent to register...'
122
+ unless @rancher.wait_for_agent @machine.id
123
+ raise Errors::AgentRegistrationTimeout,
124
+ :host => @config.hostname,
125
+ :port => @config.port
126
+ end
127
+ end
128
+ end
129
+
130
+ # configure the agent in rancher
131
+ def configure_agent
132
+ # retrieve the project id
133
+ project_id = @rancher.get_project_id
134
+ raise Errors::ProjectNotFound if project_id.nil?
135
+
136
+ # retrieve the host by the @machine.id label
137
+ host = @rancher.get_host project_id, @machine.id
138
+ raise Errors::HostNotFound, :project_id => project_id if host.nil?
139
+
140
+ # when deactivate is set and the host is active, deactivate it
141
+ if @config.deactivate and host['state'] == 'active'
142
+ @machine.ui.info "Deactivating agent..."
143
+ @rancher.deactivate_host project_id, host['id']
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,168 @@
1
+ require 'net/http'
2
+ require 'json'
3
+
4
+ module VagrantPlugins
5
+ module Rancher
6
+ class RancherClient
7
+ def initialize(hostname, port)
8
+ @hostname = hostname
9
+ @port = port
10
+ end
11
+
12
+ # waits for the rancher api to come online
13
+ def wait_for_api
14
+ uri = URI "http://#{@hostname}:#{@port}/v1"
15
+
16
+ 15.times do |i|
17
+ begin
18
+ Net::HTTP.get_response uri
19
+ break
20
+ rescue
21
+ return false if i == 15
22
+ sleep 10
23
+ end
24
+ end
25
+
26
+ true
27
+ end
28
+
29
+ # waits for the agent to register the host
30
+ def wait_for_agent(machine_id)
31
+ project_id = self.get_project_id
32
+ raise Errors::ProjectNotFound if project_id.nil?
33
+
34
+ 15.times do |i|
35
+ host = self.get_host project_id, machine_id
36
+ break unless host.nil?
37
+ return false if i == 15
38
+ sleep 10
39
+ end
40
+
41
+ true
42
+ end
43
+
44
+ # retrieves the Default project id
45
+ def get_project_id
46
+ project_id = nil
47
+
48
+ response = self.api '/v1/projects'
49
+
50
+ unless response.nil? or response['data'].empty?
51
+ response['data'].each do |project|
52
+ if project['name'] == 'Default'
53
+ project_id = project['id']
54
+ end
55
+ end
56
+ end
57
+
58
+ project_id
59
+ end
60
+
61
+ # retrieves a rancher host object
62
+ def get_host(project_id, machine_id)
63
+ host = nil
64
+
65
+ response = self.api "/v1/projects/#{project_id}/hosts"
66
+
67
+ unless response.nil? or response['data'].empty?
68
+ response['data'].each do |h|
69
+ host = h if h['labels'].values.include? machine_id
70
+ end
71
+ end
72
+
73
+ host
74
+ end
75
+
76
+ # retrieves a registration token for a project
77
+ def get_registration_token(project_id)
78
+ headers = { 'x-api-project-id' => project_id }
79
+ response = self.api '/v1/registrationtokens/', 'GET', headers
80
+
81
+ return response['data'][0] unless response['data'].empty?
82
+ nil
83
+ end
84
+
85
+ # creates a registration token for a project
86
+ def create_registration_token(project_id)
87
+ headers = { 'x-api-project-id' => project_id }
88
+ self.api '/v1/registrationtokens/', 'POST', headers
89
+ end
90
+
91
+ # configures rancher settings
92
+ def configure_setting(setting, value)
93
+ self.api "/v1/activesettings/#{setting}", 'PUT', nil, 'value' => value
94
+ end
95
+
96
+ # deactivates a host in rancher to avoid being scheduled on
97
+ def deactivate_host(project_id, host_id)
98
+ headers = { 'x-api-project-id' => project_id }
99
+ self.api "/v1/projects/#{project_id}/hosts/#{host_id}/?action=deactivate", 'POST'
100
+ end
101
+
102
+ protected
103
+
104
+ def api(path, type = 'GET', headers = nil, data = nil)
105
+ # define the connection uri to the rancher server
106
+ uri = URI("http://#{@hostname}:#{@port}#{path}")
107
+
108
+ # cheap throttle to avoid connection errors due
109
+ # to too many requests in a short time
110
+ sleep 0.1
111
+
112
+ # attempt to start the http connection
113
+ begin
114
+ Net::HTTP.start(uri.host, uri.port) do |http|
115
+ case type
116
+ when 'GET'
117
+ request = Net::HTTP::Get.new uri.request_uri
118
+ when 'POST'
119
+ request = Net::HTTP::Post.new uri.request_uri
120
+ request['Accept'] = 'application/json'
121
+ request['Content-Type'] = 'application/json'
122
+ data = {} if data.nil?
123
+ when 'PUT'
124
+ request = Net::HTTP::Put.new uri.request_uri
125
+ request['Accept'] = 'application/json'
126
+ request['Content-Type'] = 'application/json'
127
+ data = {} if data.nil?
128
+ end
129
+
130
+ # set any supplied headers
131
+ unless headers.nil?
132
+ headers.each do |key, value|
133
+ request.add_field key, value
134
+ end
135
+ end
136
+
137
+ # set data for the request
138
+ unless data.nil?
139
+ request.set_form_data data
140
+ end
141
+
142
+ # make the request
143
+ response = http.request request
144
+
145
+ # if the response code is not 2xx, then errror
146
+ unless response.code =~ /20[0-9]/
147
+ raise Errors::HttpResponseCode,
148
+ :method => type,
149
+ :host => @hostname,
150
+ :port => @port,
151
+ :path => path,
152
+ :code => response.code,
153
+ :error => response.body
154
+ end
155
+
156
+ # parse the JSON response and return an object
157
+ return JSON.parse response.body
158
+ end
159
+ rescue Exception => e
160
+ raise Errors::ApiConnectionError,
161
+ :host => @hostname,
162
+ :port => @port,
163
+ :error => e.message
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module Rancher
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,44 @@
1
+ en:
2
+ vagrant_rancher:
3
+ errors:
4
+ generic_error: |-
5
+ The vagrant-rancher plugin encountered an error.
6
+ docker_connection: |-
7
+ Could not connect to Docker daemon.
8
+ rancher_server_container: |-
9
+ Could not start the rancher server container. For more details,
10
+ please check the logs of the failed container by running the
11
+ following command on the Docker host.
12
+
13
+ docker logs rancher-server
14
+ rancher_agent_container: |-
15
+ Could not start the rancher agent bootstrap container. For more
16
+ details, please check the logs of the failed container by running
17
+ the following command on the Docker host.
18
+
19
+ docker logs rancher-agent-bootstrap
20
+ api_connection_timeout: |-
21
+ Error waiting for API to become available for
22
+ endpoint http://%{host}:%{port}.
23
+ api_connection_error: |-
24
+ There was an error connecting to the Rancher API endpoint at
25
+ http://%{host}:%{port}
26
+
27
+ The error returned was
28
+
29
+ %{error}
30
+ agent_registration_timeout: |-
31
+ Timeout waiting for agent to register to the Default project.
32
+ http_response_code: |-
33
+ Received a status code of %{code} when calling '%{method}' on
34
+ the Rancher API.
35
+
36
+ http://%{host}:%{port}%{path}
37
+
38
+ The error returned was
39
+
40
+ %{error}
41
+ project_not_found: |-
42
+ Unable to find project 'Default' in Rancher
43
+ host_not_found: |-
44
+ The Vagrant guest was not found in project %{project_id}
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vagrant-rancher/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'vagrant-rancher'
8
+ spec.version = VagrantPlugins::Rancher::VERSION
9
+ spec.authors = ['nextrevision']
10
+ spec.email = ['notarobot@nextrevision.net']
11
+
12
+ spec.summary = 'Vagrant plugin to bootstrap a Rancher environment.'
13
+ spec.description = 'Vagrant plugin to install a Rancher server and agents on all Vagrant guests.'
14
+ spec.homepage = 'https://github.com/nextrevision/vagrant-rancher'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib', 'locales']
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.11'
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-rancher
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - nextrevision
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-03-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Vagrant plugin to install a Rancher server and agents on all Vagrant
42
+ guests.
43
+ email:
44
+ - notarobot@nextrevision.net
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - .gitignore
50
+ - .rubocop.yml
51
+ - Gemfile
52
+ - LICENSE.txt
53
+ - README.md
54
+ - Rakefile
55
+ - examples/Vagrantfile
56
+ - examples/Vagrantfile.rancheros
57
+ - examples/vagrant_rancheros_guest_plugin.rb
58
+ - lib/vagrant-rancher.rb
59
+ - lib/vagrant-rancher/config.rb
60
+ - lib/vagrant-rancher/errors.rb
61
+ - lib/vagrant-rancher/plugin.rb
62
+ - lib/vagrant-rancher/provisioner.rb
63
+ - lib/vagrant-rancher/rancher.rb
64
+ - lib/vagrant-rancher/version.rb
65
+ - locales/en.yml
66
+ - vagrant-rancher.gemspec
67
+ homepage: https://github.com/nextrevision/vagrant-rancher
68
+ licenses:
69
+ - MIT
70
+ metadata: {}
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ - locales
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.0.14
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: Vagrant plugin to bootstrap a Rancher environment.
92
+ test_files: []