Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
artyomb committed Aug 14, 2024
1 parent b7e4942 commit 33bb48e
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 106 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
dry-stack (0.1.10)
dry-stack (0.1.11)

GEM
remote: https://rubygems.org/
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This gem allows ...
cat simple_stack.drs | dry-stack -e to_compose | docker stack deploy -c - simple_stack
$ dry-stack
Version: 0.1.10
Version: 0.1.11
Usage:
dry-stack -s stackfile [options] COMMAND
cat stackfile | dry-stack COMMAND
Expand Down
1 change: 0 additions & 1 deletion lib/dry-stack/command_line.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ def load_env
def safe_eval(drs, params)
Dry::Stack(params[:name], params[:configuration]) do
eval drs, self.binding
@after_blocks&.each { instance_exec &_1 }
end
end

Expand Down
38 changes: 32 additions & 6 deletions lib/dry-stack/stack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ def each_recursive(parent, each_ = -> { _1.respond_to?(:each) ? _1.each : [] },
def Stack(name = nil, configuration = nil, &)
Stack.last_stack = Stack.new name
Stack.last_stack.instance_exec(&) if block_given?
Stack.last_stack.instance_exec do
@services_blocks&.each { instance_exec &_1 }
@after_blocks&.each { instance_exec &_1 }
end
Stack.last_stack.apply_configuration configuration if configuration
end

Expand Down Expand Up @@ -147,7 +151,7 @@ def to_compose(opts = @options)

compose[:services].each do |name, service|

service[:image].gsub!(/:latest$/, '') # let docker swarm to create tag: :latest@sha265:0000...
service[:image].gsub!(/:latest$/, '') if service[:image] # let docker swarm to create tag: :latest@sha265:0000...

ingress = [@ingress[name], service[:ingress] || [] ].flatten.compact

Expand Down Expand Up @@ -332,11 +336,19 @@ def After(&block)
(@after_blocks ||=[]) << block
end

def ServicesEach(name = nil, opts = {}, &block)
def BeforeService(name = nil, opts = {}, &block)
(@before_blocks ||=[]).push names: [name].flatten.compact, except: opts[:except],
block: ->(s_name) {
_ServiceImplementation s_name, opts, &block
}
end

def AfterService(name = nil, opts = {}, &block)
After do
name ||= @services.keys
[name].flatten.each do |s_name|
Service s_name, opts, &block
names = [name || @services.keys].flatten
names -= [opts[:except]].flatten if opts.key? :except
names.each do |s_name|
_ServiceImplementation s_name, opts, &block
end
end
end
Expand All @@ -345,7 +357,21 @@ def PublishPorts(ports)
@publish_ports.merge! ports.to_h { |k, v| [k,[v].flatten] }
end

def Service(name, opts = {}, &)
def Service(name, opts = {}, &block)
@services_blocks ||=[]
(@services_blocks ||=[]).push -> { _ServiceDeferred(name, opts, &block) }
end

def _ServiceDeferred(name, opts = {}, &block)
(@before_blocks || []).each do |before|
next unless before[:names].empty? || before[:names].include?(name)
next if before[:except]&.include? name
before[:block].call(name)
end
_ServiceImplementation(name, opts, &block)
end

def _ServiceImplementation(name, opts = {}, &)
opts = opts.dup
opts[:ports] = [opts[:ports]].flatten if opts.key? :ports
opts[:environment] = opts.delete(:env) if opts.key? :env
Expand Down
2 changes: 1 addition & 1 deletion lib/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Dry
class Stack
VERSION = '0.1.10'
VERSION = '0.1.11'
end
end
86 changes: 42 additions & 44 deletions spec/data/stack1.drs
Original file line number Diff line number Diff line change
@@ -1,45 +1,43 @@
Stack :simple_stack do
Options traefik: true, ingress: true
Labels 'stack.product': 'product A'

SYSLOG = { driver: 'syslog', options: {
'syslog-address': 'tcp://swarm.next:5005',
'tag': 'image:{{.ImageName}}/service:{{.Name}}/container:{{.ID}}'
} }
FLUENTD = { driver: 'fluentd', options: {
'fluentd-address': 'fluentd:24224',
'fluentd-async': true
} }

Ingress operator: { host: 'operator.*' },
navigator: { host: 'navigator.*' }

Environment [:backend, :reports], {
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: 'http://open.tl/v1/traces',
NODE_ENV: 'production',
OTEL_RESOURCE_ATTRIBUTES: "deployment.environment=%{stack-name},service.name=%{service-name}"
}

PublishPorts admin: 4000, operator: [4001,4002]
PublishPorts navigator: '4002:5000', reports: [7000,'2000:3000'] # mode: ingress, protocol: tcp
Deploy backend: { replica: 2, 'resources.limits': { cpus: 4, memory: '500M' } }
Ingress backend: [{host: 'backend.*'}, {host: 'admin.*', path: '/api', port: 4000}]

Service :admin, image: 'frontend', env: {APP: 'admin'}, ports: 5000 do
deploy_label 'traefik.http.middlewares.%{service-name}_auth.basicauth.users=admin:$apr1$i7hdbc9g$Rkocxo9snhmuESvUg0TTv/'
deploy_label "traefik.http.routers.%{service-name}.middlewares=%{service-name}_auth"
logging SYSLOG
end
Service :operator, image: 'frontend', env: {APP: 'operator'}, ports: [5000, 6000]
Service :navigator, image: 'frontend', env: {APP: 'navigator'}, ports: 5000

Service :backend, image: 'backend', ports: 3000 do
user :root
env APP_PORT: 3000, NODE_ENV: 'development', SKIP_GZ: true, DB_URL: '$DB_URL'
logging FLUENTD
end

Service :reports, image: 'reports:0.1', env: {DB_URL: '$DB_URL'}, ports: 7000

Network :default, attachable: true
Options name: :simple_stack, traefik: true, ingress: true
Labels 'stack.product': 'product A'

SYSLOG = { driver: 'syslog', options: {
'syslog-address': 'tcp://swarm.next:5005',
'tag': 'image:{{.ImageName}}/service:{{.Name}}/container:{{.ID}}'
} }
FLUENTD = { driver: 'fluentd', options: {
'fluentd-address': 'fluentd:24224',
'fluentd-async': true
} }

Ingress operator: { host: 'operator.*' },
navigator: { host: 'navigator.*' }

Environment [:backend, :reports], {
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: 'http://open.tl/v1/traces',
NODE_ENV: 'production',
OTEL_RESOURCE_ATTRIBUTES: "deployment.environment=%{stack-name},service.name=%{service-name}"
}

PublishPorts admin: 4000, operator: [4001,4002]
PublishPorts navigator: '4002:5000', reports: [7000,'2000:3000'] # mode: ingress, protocol: tcp
Deploy backend: { replica: 2, 'resources.limits': { cpus: 4, memory: '500M' } }
Ingress backend: [{host: 'backend.*'}, {host: 'admin.*', path: '/api', port: 4000}]

Service :admin, image: 'frontend', env: {APP: 'admin'}, ports: 5000 do
deploy_label 'traefik.http.middlewares.%{service-name}_auth.basicauth.users=admin:$apr1$i7hdbc9g$Rkocxo9snhmuESvUg0TTv/'
deploy_label "traefik.http.routers.%{service-name}.middlewares=%{service-name}_auth"
logging SYSLOG
end
Service :operator, image: 'frontend', env: {APP: 'operator'}, ports: [5000, 6000]
Service :navigator, image: 'frontend', env: {APP: 'navigator'}, ports: 5000

Service :backend, image: 'backend', ports: 3000 do
user :root
env APP_PORT: 3000, NODE_ENV: 'development', SKIP_GZ: true, DB_URL: '$DB_URL'
logging FLUENTD
end

Service :reports, image: 'reports:0.1', env: {DB_URL: '$DB_URL'}, ports: 7000

Network :default, attachable: true
4 changes: 3 additions & 1 deletion spec/data/stack16-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ services:
OTEL_LOG_LEVEL: error
OTEL_TRACES_EXPORTER: otlp
REPLICA: "{{.Task.Slot}}"
FRONT_CONF2: base2
FRONT_BEFORE: before
FRONT_OVER: over2
CONSOLE_LEVEL: error
SERVICE_INFO: 'true'
FRONT_CONF: base4
FRONT_CONF2: base_1
CONF: base1
STACK_NAME: stack_name
STACK_SERVICE_NAME: front
Expand Down
20 changes: 16 additions & 4 deletions spec/data/stack16.drs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Service :admin, image: 'frontend:latest', ports: 5000 do
dns ['7.7.4.4','6.6.4.4']
end

ServicesEach do
AfterService do
network name: 'grafana-network', external: true
network :default

Expand All @@ -32,15 +32,27 @@ ServicesEach do
REPLICA: "{{.Task.Slot}}"
end

ServicesEach :front do
AfterService :front do
env FRONT_CONF: 'base1'
env FRONT_OVER: 'over'
end

ServicesEach :front, env: {FRONT_CONF2: 'base_1'} do
AfterService :front, env: { FRONT_CONF2: 'base_1'} do
env FRONT_CONF: 'base2'
end

ServicesEach [:front, :admin], env: {FRONT_CONF: 'base_3'} do
AfterService :front, env: { FRONT_CONF2: 'base_1'} do
env FRONT_OVER: 'over2'
env FRONT_CONF2: 'base2'
end

BeforeService :front, env: { FRONT_CONF2: 'base_1'} do
env FRONT_BEFORE: 'before'
env FRONT_OVER: 'before'
env FRONT_CONF2: 'before'
end

AfterService [:front, :admin], env: { FRONT_CONF: 'base_3'} do
env CONF: 'base1'
env FRONT_CONF: 'base4'
end
91 changes: 44 additions & 47 deletions spec/data/stack2.drs
Original file line number Diff line number Diff line change
@@ -1,51 +1,48 @@

Stack :name1 do
Options traefik: true, ingress: true

Logging :svc1, driver: 'fluentd', options: {
'fluentd-address': 'fluentd1t:24224',
Options name: :name1, traefik: true, ingress: true

Logging :svc1, driver: 'fluentd', options: {
'fluentd-address': 'fluentd1t:24224',
'fluentd-async': true
}

Logging [:svc1, :svc2], driver: 'fluentd', options: {
'fluentd-address': 'fluentd2:24224',
'fluentd-async': true
}
Ingress svc1: [
{host: 'backend.*'},
{host: 'admin.*', path: '/api', port: 4000}
]

Deploy [:svc1, :svc2], 'placement.constraints': ['node.role == manager']

Deploy [:svc1, :svc2], labels: [
'traefik.http.middlewares.%{service-name}_auth.basicauth.users=admin:$$apr1$$i7hdbc9g$$Rkocxo9snhmuESvUg0TTv/',
"traefik.http.routers.%{service-name}.middlewares=%{service-name}_auth"
]

Service :svc1, image: 'service-image'
Service :svc2, image: 'postgres:13.5-alpine', ingress: {host: 'svc2.*', port: 3000} do
command 'bash -c "apk add curl && docker-entrypoint.sh -c \"shared_buffers=256MB\" -c \"max_connections=200\" "'
entrypoint '/usr/bin/tini -- wait-for-it opensearch:9200 -- /docker-entrypoint.sh'

logging driver: 'fluentd', options: {
'fluentd-address': 'fluentd3:24224',
'fluentd-async': true
}
end

Logging [:svc1, :svc2], driver: 'fluentd', options: {
'fluentd-address': 'fluentd2:24224',
'fluentd-async': true
}
Ingress svc1: [
{host: 'backend.*'},
{host: 'admin.*', path: '/api', port: 4000}
]

Deploy [:svc1, :svc2], 'placement.constraints': ['node.role == manager']

Deploy [:svc1, :svc2], labels: [
'traefik.http.middlewares.%{service-name}_auth.basicauth.users=admin:$$apr1$$i7hdbc9g$$Rkocxo9snhmuESvUg0TTv/',
"traefik.http.routers.%{service-name}.middlewares=%{service-name}_auth"
]

Service :svc1, image: 'service-image'
Service :svc2, image: 'postgres:13.5-alpine', ingress: {host: 'svc2.*', port: 3000} do
command 'bash -c "apk add curl && docker-entrypoint.sh -c \"shared_buffers=256MB\" -c \"max_connections=200\" "'
entrypoint '/usr/bin/tini -- wait-for-it opensearch:9200 -- /docker-entrypoint.sh'

logging driver: 'fluentd', options: {
'fluentd-address': 'fluentd3:24224',
'fluentd-async': true
}
end

Service :svc3, image: 'service-image' do
ingress host: 'svc3.*', port: 3000
ingress host: 'svc3-1.*', port: 4000
end

Service :svc4, image: 'service-image' do
ingress [{ host: 'svc4.*', port: 3000 }, { host: 'svc4-1.*', port: 4000 }]
end

Service :svc5, image: 'postgres:13.5-alpine', ingress: [{ host: 'svc5.*', port: 3000 }, { host: 'svc5-1.*', port: 4000 }]

Service :svc6, image: 'postgres:13.5-alpine', ingress: [{ host: 'svc6.*', port: 3000 }] do
ingress host: 'svc6-1.*', port: 4000
end
Service :svc3, image: 'service-image' do
ingress host: 'svc3.*', port: 3000
ingress host: 'svc3-1.*', port: 4000
end

Service :svc4, image: 'service-image' do
ingress [{ host: 'svc4.*', port: 3000 }, { host: 'svc4-1.*', port: 4000 }]
end

Service :svc5, image: 'postgres:13.5-alpine', ingress: [{ host: 'svc5.*', port: 3000 }, { host: 'svc5-1.*', port: 4000 }]

Service :svc6, image: 'postgres:13.5-alpine', ingress: [{ host: 'svc6.*', port: 3000 }] do
ingress host: 'svc6-1.*', port: 4000
end

0 comments on commit 33bb48e

Please sign in to comment.