Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Feature/swarm #940

Draft
wants to merge 21 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a8d2679
Initial work on docker swarm support. docker_swarm_manager
elthariel Nov 24, 2017
0a22976
Add docker_swarm worker and overlay_network
elthariel Nov 24, 2017
6bf6764
Initial implementation of docker_swarm_service
elthariel Nov 24, 2017
9b974e9
Fix current_swarm
elthariel Nov 24, 2017
69f109a
Minor fixes
elthariel Nov 24, 2017
2cb0c12
Fix autoload version
elthariel Nov 24, 2017
29d2698
ports is an array of hash, not a hash
elthariel Nov 30, 2017
db4e82d
Add update action to docker_swarm_service
elthariel Nov 30, 2017
37191c0
Update service spec generation to fix idempotency
elthariel Nov 30, 2017
ceba185
Add restart & force_update actions
elthariel Jan 12, 2018
f890594
Add support for restart_xxx attributes
elthariel Jan 12, 2018
e062a0e
Fix force_update action, remove buggy restart action
elthariel Jan 16, 2018
80f4d3e
Add support for hostname
elthariel Jan 18, 2018
4e80cd6
Remove use of Boolean in property in favor of [TrueClass, FalseClass]
elthariel Jun 7, 2019
e5e46bb
Remove use of remove NonEmptyArray property type
elthariel Jun 7, 2019
6c51457
swarm_service: Add Mounts support
elthariel Jun 7, 2019
eb2c5fc
swarm_service: Only add `Mounts` field if it is not empty
elthariel Jun 11, 2019
4996b31
helpers_swarm_service: Do not add the Consistency field if its unset
elthariel Jun 13, 2019
1d64029
Adds health_start_period to docker_swarm_service
elthariel May 26, 2020
4013f6f
! Add missing health checks fields
elthariel Jul 14, 2020
d09bc0a
! Reset cached swarm current_service at update. Remove non mandatory …
elthariel Jul 14, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions libraries/_autoload.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
begin
gem 'docker-api', '= 1.33.6'
rescue LoadError
unless defined?(ChefSpec)
run_context = Chef::RunContext.new(Chef::Node.new, {}, Chef::EventDispatch::Dispatcher.new)

require 'chef/resource/chef_gem'

docker = Chef::Resource::ChefGem.new('docker-api', run_context)
docker.version '= 1.33.6'
docker.run_action(:install)
end
end

begin
gem 'docker-swarm-sdk', '~> 1.2.4'
rescue LoadError
unless defined?(ChefSpec)
run_context = Chef::RunContext.new(Chef::Node.new, {}, Chef::EventDispatch::Dispatcher.new)

require 'chef/resource/chef_gem'

docker = Chef::Resource::ChefGem.new('docker-swarm-sdk', run_context)
docker.version '= 1.2.4'
docker.run_action(:install)
end
end
14 changes: 14 additions & 0 deletions libraries/docker_swarm_base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module DockerCookbook
# We override the DockerBase to use the Docker Swarm SDK Connection object
class DockerSwarmBase < DockerBase
require_relative 'helpers_base'
include DockerHelpers::Base
require_relative 'helpers_swarm_base'
include DockerHelpers::SwarmBase

property :host, [String, nil], default: lazy { default_host }, desired_state: false

def swarm_info
end
end
end
46 changes: 46 additions & 0 deletions libraries/docker_swarm_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'docker-swarm'

module DockerCookbook
require_relative 'docker_swarm_node_base'
# Docker swarm manager init and join
class DockerSwarmManager < DockerSwarmNodeBase
require_relative 'helpers_swarm_cluster'

include DockerHelpers::SwarmCluster

# Resource properties
resource_name :docker_swarm_manager

property :first_manager, [TrueClass, FalseClass], default: false

declare_action_class.class_eval do
def whyrun_supported?
true
end
end

#########
# Actions
#########

default_action :create

action :create do
ensure_swarm_available!
return if cluster_initialized?

if new_resource.first_manager
converge_by 'Running swarm init' do
manager_init
end
else
if join_address.nil? || join_token.nil?
raise 'Provide join_address & join_token or set `first_manager true`'
end
converge_by 'Running swarm join' do
cluster_join(:manager, join_address, join_token)
end
end
end
end
end
44 changes: 44 additions & 0 deletions libraries/docker_swarm_node_base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require 'docker-swarm'

module DockerCookbook
# Initialize a docker swarm
class DockerSwarmNodeBase < DockerSwarmBase
require_relative 'helpers_swarm_cluster'

include DockerHelpers::SwarmCluster

property :cluster_name, String, name_propery: true
property :listen_address, String, default: '0.0.0.0'

property :join_address, String
property :join_token, String
property :force_leave, [TrueClass, FalseClass], default: true

property :drain_opts, Hash, default: {}

declare_action_class.class_eval do
def whyrun_supported?
true
end
end

action :drain do
ensure_swarm_available!
return unless cluster_initialized?
return if current_swarm_node.running_tasks == 0

converge_by 'Draining node' do
current_swarm_node.drain(drain_opts)
end
end

action :destroy do
ensure_swarm_available!
return unless cluster_initialized?

converge_by "Leaving the cluster (force=#{force_leave})" do
cluster_leave(force_leave)
end
end
end
end
46 changes: 46 additions & 0 deletions libraries/docker_swarm_overlay_network.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'docker-swarm'

module DockerCookbook
# Initialize a docker swarm
class DockerSwarmOverlayNetwork < DockerSwarmBase
require_relative 'helpers_swarm_network'

include DockerHelpers::SwarmNetwork

# Resource properties
resource_name :docker_swarm_overlay_network
property :network_name, String, name_propery: true

declare_action_class.class_eval do
def whyrun_supported?
true
end
end

#########
# Actions
#########

default_action :create

action :create do
ensure_swarm_available!
return if network_find(new_resource.name)

converge_by 'Create overlay network' do
create_overlay_network(new_resource.name)
end
end

action :destroy do
ensure_swarm_available!

network = network_find(new_resource.name)
return unless network

converge_by 'Destroying network' do
remove_overlay_network(network)
end
end
end
end
108 changes: 108 additions & 0 deletions libraries/docker_swarm_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
require 'docker-swarm'

module DockerCookbook
# Initialize a docker swarm
class DockerSwarmService < DockerSwarmBase
require_relative 'helpers_swarm_service'

include DockerHelpers::SwarmService

resource_name :docker_swarm_service

property :service_name, String, name_propery: true

property :image, String, required: true
property :user, String, required: true, default: 'root'
property :networks, [Array, nil], required: true,
coerce: proc { |v| Array(v).empty? ? nil : Array(v) }
property :hostname, String

property :environment, Hash, default: {}
property :log_driver, String, required: true, default: 'json-file'
property :log_driver_opts, Hash,
default: { 'max-file' => '3', 'max-size' => '10M' }

property :limits, Hash, default: {}
property :reservations, Hash, default: {}

property :restart_condition, String, required: true, default: 'on-failure'
property :restart_delay, Integer, required: true, default: 1
property :restart_attempts, Integer, required: true, default: 3

property :health_start_period, Integer, required: true, default: 10

property :global, [TrueClass, FalseClass], required: true, default: false
property :replicas, Integer, default: 1
property :ports, Array, default: []
property :labels, Hash, default: {}
property :mounts, Array, default: []

%i(update rollback).each do |kind|
property "#{kind}_parallelism".to_sym, Integer, required: true, default: 1
property "#{kind}_delay".to_sym, Integer, required: true, default: 1
property "#{kind}_monitor".to_sym, Integer, required: true, default: 15
property "#{kind}_max_failure_ratio".to_sym, Float,
required: true,
default: 0.0
property "#{kind}_failure_action".to_sym, %w(pause continue rollback),
required: true,
default: 'pause'
end

declare_action_class.class_eval do
def whyrun_supported?
true
end
end

#########
# Actions
#########

default_action :create

action :create do
ensure_swarm_available!

if current_service.nil?
converge_by('Create service') { create_service }
elsif current_service_changed?
converge_by('Update service') { update_service }
end
end

action :update do
ensure_swarm_available!

# To avoid using a stale version of the current service spec when
# executing two actions against the same resource in the same run (and
# have an out of sequence ForceUpdate counter). We reset our cached
# service spec before every update
reset_current_service

if current_service_changed?
converge_by('Update service') { update_service }
end
end

action :force_update do
ensure_swarm_available!

# See #update comment
reset_current_service

converge_by('Update service [forced]') do
update_service(true)
end
end

action :destroy do
ensure_swarm_available!
return unless current_service

converge_by 'Delete service' do
current_service.remove
end
end
end
end
38 changes: 38 additions & 0 deletions libraries/docker_swarm_worker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require 'docker-swarm'

module DockerCookbook
require_relative 'docker_swarm_node_base'
# Initialize a docker swarm worker
class DockerSwarmWorker < DockerSwarmNodeBase
require_relative 'helpers_swarm_cluster'

include DockerHelpers::SwarmCluster

# Resource properties
resource_name :docker_swarm_worker

declare_action_class.class_eval do
def whyrun_supported?
true
end
end

#########
# Actions
#########

default_action :create

action :create do
ensure_swarm_available!
return if cluster_initialized?

if join_address.nil? || join_token.nil?
raise 'Provide join_address & join_token'
end
converge_by 'Running swarm join' do
cluster_join(:worker, join_address, join_token)
end
end
end
end
Loading
Loading