Module: Dklet::DSL

Defined in:
lib/dklet/dsl.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.dsl_method(mthd) ⇒ Object



11
12
13
14
15
16
# File 'lib/dklet/dsl.rb', line 11

def dsl_method(mthd)
  dsl_methods << mthd
  define_method(mthd) do
    fetch_with_default(mthd)
  end
end

.dsl_methodsObject



7
8
9
# File 'lib/dklet/dsl.rb', line 7

def dsl_methods
  @_dsl_methods ||= []
end

.registryObject



3
4
5
# File 'lib/dklet/dsl.rb', line 3

def registry
  @_registry ||= {}
end

Instance Method Details

#add_dsl(&blk) ⇒ Object



23
24
25
# File 'lib/dklet/dsl.rb', line 23

def add_dsl &blk
  Dklet::DSL.module_eval &blk
end

#add_note(str) ⇒ Object



226
227
228
# File 'lib/dklet/dsl.rb', line 226

def add_note str
  (registry[:user_notes] ||= []) << str
end

#app_releaseObject

标识一次运行发布的用途, 如redis for hirails-only



373
374
375
# File 'lib/dklet/dsl.rb', line 373

def app_release
  ENV['APP_RELEASE'] || 'default'
end

#app_tagsObject



306
307
308
# File 'lib/dklet/dsl.rb', line 306

def app_tags
  registry[:app_tags] ||= []
end

#appnameObject



288
289
290
# File 'lib/dklet/dsl.rb', line 288

def appname
  fetch(:appname) || script_name
end

#approotObject



284
285
286
# File 'lib/dklet/dsl.rb', line 284

def approot
  fetch(:approot) || build_root || script_path
end

#before_task(name = :main, &blk) ⇒ Object



209
210
211
# File 'lib/dklet/dsl.rb', line 209

def before_task(name = :main, &blk)
  task(name, type: :before, &blk)
end

#build_netObject



331
332
333
# File 'lib/dklet/dsl.rb', line 331

def build_net
  fetch(:build_net)
end

#build_rootObject



323
324
325
# File 'lib/dklet/dsl.rb', line 323

def build_root
  fetch(:build_root)
end

#compose_cmdObject

-f, –file -p, –project-name to altertive project name, eg. default net prefix



276
277
278
# File 'lib/dklet/dsl.rb', line 276

def compose_cmd
  "docker-compose -f #{specfile} --project-name #{compose_name} --project-directory #{approot}"
end

#compose_nameObject

project name for docker-compose



270
271
272
# File 'lib/dklet/dsl.rb', line 270

def compose_name
  "#{fetch(:compose_name) || appname}_#{env}"
end

#container_filters_for_releaseObject



95
96
97
98
99
# File 'lib/dklet/dsl.rb', line 95

def container_filters_for_release
  release_label_hash.map do |k, v|
    "--filter label=#{k}=#{v}"
  end.join(' ')
end

#container_missingObject



352
353
354
# File 'lib/dklet/dsl.rb', line 352

def container_missing
  puts "Not found container for image: #{docker_image}"
end

#containers_for_image(img = docker_image) ⇒ Object

Note: if img1:t1 = img2:t2 points to same image hashid, they will be selected as same



106
107
108
# File 'lib/dklet/dsl.rb', line 106

def containers_for_image(img = docker_image)
  `docker ps -aq -f ancestor=#{img}`.split("\n")
end

#containers_for_releaseObject



101
102
103
# File 'lib/dklet/dsl.rb', line 101

def containers_for_release
  `docker ps -aq #{container_filters_for_release}`.split("\n")
end

#containers_in_net(net = netname) ⇒ Object



110
111
112
# File 'lib/dklet/dsl.rb', line 110

def containers_in_net(net = netname)
  `docker ps -aq -f network=#{net}`.split("\n")
end

#custom_commands(&blk) ⇒ Object



222
223
224
# File 'lib/dklet/dsl.rb', line 222

def custom_commands &blk
  DockletCLI.class_eval &blk
end

#default_app_volumesObject



390
391
392
# File 'lib/dklet/dsl.rb', line 390

def default_app_volumes
  volumes_root.join(release_path_name)
end

#default_container_nameObject



348
349
350
# File 'lib/dklet/dsl.rb', line 348

def default_container_name
  full_release_name
end

#default_docker_imageObject

release is not relevant



55
56
57
# File 'lib/dklet/dsl.rb', line 55

def default_docker_image
  "#{env}/#{appname}:#{image_tag}"
end

#default_image_labelsObject



63
64
65
# File 'lib/dklet/dsl.rb', line 63

def default_image_labels
  "maintainer=dailyops built_from=dklet"
end

#default_image_tagObject



59
60
61
# File 'lib/dklet/dsl.rb', line 59

def default_image_tag
  "edge"
end

#default_ops_containerObject



344
345
346
# File 'lib/dklet/dsl.rb', line 344

def default_ops_container
  containers_for_release.first # || container_name
end

#disable(key) ⇒ Object



193
194
195
# File 'lib/dklet/dsl.rb', line 193

def disable(key)
  (registry[:disable] ||= {})[key] = true
end

#disabled?(key) ⇒ Boolean

Returns:

  • (Boolean)


197
198
199
# File 'lib/dklet/dsl.rb', line 197

def disabled?(key)
  (registry[:disable] ||= {})[key]
end

#dklet_config_for(name) ⇒ Object

todo



151
152
153
154
155
# File 'lib/dklet/dsl.rb', line 151

def dklet_config_for(name)
  p = Pathname("/dkconf/#{full_release_name}")
  p.mkpath unless p.directory?
  p.join(name)
end

#dklet_scriptObject



114
115
116
# File 'lib/dklet/dsl.rb', line 114

def dklet_script
  Pathname($PROGRAM_NAME)
end

#dkrun_cmd(labeled: true, opts: nil, named: false) ⇒ Object

maybe from external image



76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/dklet/dsl.rb', line 76

def dkrun_cmd(labeled: true, opts: nil, named: false)
  cmd = "docker run"
  if labeled
    release_labels = release_label_hash.map do |k, v|
      "--label=#{k}=#{v}"
    end.join(' ')
    cmd += " #{release_labels}"
  end
  cmd += " --net #{netname}" if netname
  cmd += " --name #{container_name}" if named
  cmd += " #{opts}" if opts
  cmd
end

#dktmprun(opts: nil) ⇒ Object



90
91
92
93
# File 'lib/dklet/dsl.rb', line 90

def dktmprun(opts: nil)
  cmd = dkrun_cmd(opts: "--rm -i #{opts}", labeled: false)
  "#{cmd} #{docker_image}"
end

#dockerfileObject



175
176
177
# File 'lib/dklet/dsl.rb', line 175

def dockerfile
  rendered_file_for(:dockerfile)
end

#dsl_methodsObject



27
28
29
# File 'lib/dklet/dsl.rb', line 27

def dsl_methods
  Dklet::DSL.dsl_methods
end

#ensure_docker_net(name, driver: :bridge) ⇒ Object



244
245
246
247
248
249
250
# File 'lib/dklet/dsl.rb', line 244

def ensure_docker_net(name, driver: :bridge)
  unless netid = find_net(name)
    puts "create new network: #{name}"
    netid = `docker network create #{name} --label #{label_pair(:name, name)} --driver=#{driver}`
  end
  netid
end

#envObject



360
361
362
# File 'lib/dklet/dsl.rb', line 360

def env
  ENV['APP_ENV'] || fetch(:default_env) || 'dev'
end

#fetch(key) ⇒ Object



35
36
37
38
39
40
41
# File 'lib/dklet/dsl.rb', line 35

def fetch(key)
  val = registry[key]
  if val && val.respond_to?(:call)
    val = val.call
  end
  val
end

#fetch_with_default(key) ⇒ Object



43
44
45
46
47
48
# File 'lib/dklet/dsl.rb', line 43

def fetch_with_default(key)
  provided = fetch(key)
  return provided if provided
  mthd = "default_#{key}"
  send(mthd) if respond_to?(mthd)
end

#file_content_for(name) ⇒ Object



144
145
146
147
148
# File 'lib/dklet/dsl.rb', line 144

def file_content_for(name)
  fpath = fetch(name)
  return unless fpath
  File.read(fpath)
end

#file_for(name) ⇒ Object



140
141
142
# File 'lib/dklet/dsl.rb', line 140

def file_for(name)
  fetch(name)
end

#find_net(name) ⇒ Object

use label (not name) filter to avoid str part match



253
254
255
256
257
258
# File 'lib/dklet/dsl.rb', line 253

def find_net(name)
  cmd = "docker network ls -q --filter label=#{label_pair(:name, name)}"
  netid = `#{cmd}`.chomp
  return netid unless netid.empty?
  nil
end

#full_release_nameObject

take into acccount: app, env, app_release



293
294
295
# File 'lib/dklet/dsl.rb', line 293

def full_release_name
  [env, appname, app_release].compact.join('_')
end

#host_domain_in_containerObject

ref dklet/mac/hostnet



419
420
421
# File 'lib/dklet/dsl.rb', line 419

def host_domain_in_container
  ENV['HOST_DOMAIN_IN_CONTAINER'] || 'host.dokcer.internal'
end

#host_port_for(cport) ⇒ Object



434
435
436
# File 'lib/dklet/dsl.rb', line 434

def host_port_for(cport)
  host_with_port_for(cport, only_port: true)
end

#host_with_port_for(cport, host_ip: true, only_port: false) ⇒ Object

0.0.0.0:32879



424
425
426
427
428
429
430
431
432
# File 'lib/dklet/dsl.rb', line 424

def host_with_port_for(cport, host_ip: true, only_port: false )
  str = `docker port #{ops_container} #{cport}`.chomp 
  return if str.empty?
  if only_port
    return str.split(':').last
  end
  return str unless host_ip
  str.sub('0.0.0.0', Dklet::Util.host_ip)
end

#in_dev?Boolean

Returns:

  • (Boolean)


364
365
366
# File 'lib/dklet/dsl.rb', line 364

def in_dev?
  env =~ /^dev/
end

#in_prod?Boolean

Returns:

  • (Boolean)


368
369
370
# File 'lib/dklet/dsl.rb', line 368

def in_prod?
  env =~ /^prod/
end

#label_key(key, prefix: true) ⇒ Object



260
261
262
# File 'lib/dklet/dsl.rb', line 260

def label_key(key, prefix: true)
  prefix ? "docklet.#{key}" : key
end

#label_pair(key, val, prefix: true) ⇒ Object

key=value pair



265
266
267
# File 'lib/dklet/dsl.rb', line 265

def label_pair(key, val, prefix: true)
  [label_key(key, prefix: prefix), val].join('=')
end

#let_cli_magic_start!Object



218
219
220
# File 'lib/dklet/dsl.rb', line 218

def let_cli_magic_start!
  DockletCLI.start
end

#netnameObject



240
241
242
# File 'lib/dklet/dsl.rb', line 240

def netname
  fetch(:netname)
end

#proxy_domain_baseObject

top proxy domain part



400
401
402
# File 'lib/dklet/dsl.rb', line 400

def proxy_domain_base
  ENV['PROXY_DOMAIN_BASE'] || 'lh'
end

#proxy_domains(*doms) ⇒ Object



404
405
406
407
408
409
410
411
412
413
414
415
416
# File 'lib/dklet/dsl.rb', line 404

def proxy_domains(*doms)
  if doms.empty?
    doms = fetch(:domains)
    doms = [appname] if doms.nil? or doms.empty?
  end

  denv = env
  denv = nil if denv =~ /^prod/

  doms.map do |d| 
    [d, denv, proxy_domain_base].compact.join('.')
  end.join(',') 
end

#raw_dockerfileObject



171
172
173
# File 'lib/dklet/dsl.rb', line 171

def raw_dockerfile
  fetch(:dockerfile)
end

#raw_specfileObject



184
185
186
# File 'lib/dklet/dsl.rb', line 184

def raw_specfile
  fetch(:specfile)
end

#register(key, value) ⇒ Object



31
32
33
# File 'lib/dklet/dsl.rb', line 31

def register(key, value)
  registry[key] = value
end

#register_app_tag(tag) ⇒ Object



302
303
304
# File 'lib/dklet/dsl.rb', line 302

def register_app_tag(tag)
  app_tags << tag
end

#register_approot(path) ⇒ Object



280
281
282
# File 'lib/dklet/dsl.rb', line 280

def register_approot path
  register_path(:approot, path)
end

#register_build_net(net) ⇒ Object



327
328
329
# File 'lib/dklet/dsl.rb', line 327

def register_build_net net
  register(:build_net, net)
end

#register_build_root(path) ⇒ Object



319
320
321
# File 'lib/dklet/dsl.rb', line 319

def register_build_root path
  register_path(:build_root, path)
end

#register_default_env(str) ⇒ Object



356
357
358
# File 'lib/dklet/dsl.rb', line 356

def register_default_env(str)
  register :default_env, str
end

#register_docker_image(name) ⇒ Object



50
51
52
# File 'lib/dklet/dsl.rb', line 50

def register_docker_image(name)
  register :docker_image, name
end

#register_domain(*doms) ⇒ Object

domain



395
396
397
# File 'lib/dklet/dsl.rb', line 395

def register_domain(*doms)
  register :domains, doms
end

#register_net(name = :dailyops, build: false) ⇒ Object

docker networking



235
236
237
238
# File 'lib/dklet/dsl.rb', line 235

def register_net(name = :dailyops, build: false)
  register :netname, name
  ensure_docker_net(name) if build
end

#register_ops(cid) ⇒ Object



340
341
342
# File 'lib/dklet/dsl.rb', line 340

def register_ops(cid)
  register :ops_container, cid
end

#register_path(key, path) ⇒ Object



335
336
337
338
# File 'lib/dklet/dsl.rb', line 335

def register_path key, path
  path = Pathname(path) unless path.is_a?(Pathname)
  register key, path
end

#registryObject



19
20
21
# File 'lib/dklet/dsl.rb', line 19

def registry
  Dklet::DSL.registry
end

#release_label_hashObject



67
68
69
70
71
72
73
# File 'lib/dklet/dsl.rb', line 67

def release_label_hash
  {
    dklet_env: env,
    dklet_app: appname,
    dklet_release: app_release
  }
end

#release_path_nameObject

make path friendly



298
299
300
# File 'lib/dklet/dsl.rb', line 298

def release_path_name
  full_release_name.gsub(/_/, '-')
end

#rendered_file_for(name, locals: {}, in_binding: binding) ⇒ Object



157
158
159
160
161
162
163
# File 'lib/dklet/dsl.rb', line 157

def rendered_file_for(name, locals: {}, in_binding: binding)
  tmpl = file_content_for(name)
  return unless tmpl
  erb = ERB.new(tmpl, nil, '%<>')
  rendered = erb.result(in_binding)
  tmpfile_for(rendered)
end

#script_nameObject

use <parent_path_name>_<script_file_name> to ensure possible unique



124
125
126
127
128
129
130
# File 'lib/dklet/dsl.rb', line 124

def script_name # not file name
  sname = fetch(:script_name)
  return sname if sname
  name = dklet_script.basename('.rb').to_s
  pname = script_path.basename.to_s
  "#{pname}_#{name}"
end

#script_pathObject

触发脚本所在(绝对)路径



119
120
121
# File 'lib/dklet/dsl.rb', line 119

def script_path
  dklet_script.realdirpath.dirname
end

#set_file_for(name, str) ⇒ Object



136
137
138
# File 'lib/dklet/dsl.rb', line 136

def set_file_for(name, str)
  register name, tmpfile_for(str)
end

#smart_build_context_pathObject



310
311
312
313
314
315
316
317
# File 'lib/dklet/dsl.rb', line 310

def smart_build_context_path
  # use explicitly specified, maybe nil
  return build_root if registry.has_key?(:build_root)
  # check build path dependent
  body = File.read(dockerfile)
  need_path = body =~ /^\s*(ADD|COPY)\s/i
  script_path if need_path
end

#specfileObject

rendered in current context



189
190
191
# File 'lib/dklet/dsl.rb', line 189

def specfile
  rendered_file_for(:specfile)
end

#task(name = :main, opts = {}, &blk) ⇒ Object

main dsl



202
203
204
205
206
207
# File 'lib/dklet/dsl.rb', line 202

def task(name = :main, opts={}, &blk)
  type = opts.delete(:type) || :after
  hooks_name = "#{name}_#{type}_hooks".to_sym 
  (registry[hooks_name] ||= []) << blk
  task_opts(name).merge!(opts) unless opts.empty?
end

#task_opts(name = :main) ⇒ Object



213
214
215
216
# File 'lib/dklet/dsl.rb', line 213

def task_opts(name = :main)
  key = "opts_for_task_#{name}".to_sym
  registry[key] ||= {}
end

#tmpfile_for(str) ⇒ Object



132
133
134
# File 'lib/dklet/dsl.rb', line 132

def tmpfile_for(str)
  Dklet::Util.tmpfile_for(str)
end

#user_notesObject



230
231
232
# File 'lib/dklet/dsl.rb', line 230

def user_notes
  fetch(:user_notes)
end

#volumes_rootObject



377
378
379
380
381
382
383
384
385
386
387
388
# File 'lib/dklet/dsl.rb', line 377

def volumes_root
  vols_root = "#{ENV['HOME']}/DockerVolumes"
  root = fetch(:volumes_root) || if File.directory?(vols_root)
      # friendly to File sharing on Docker for Mac
      vols_root
    else
      '~/docker-volumes'
    end
  proot = Pathname(root)
  proot.mkpath unless proot.directory?
  proot
end

#write_dockerfile(str, path: nil) ⇒ Object

Dockerfile for image build



166
167
168
169
# File 'lib/dklet/dsl.rb', line 166

def write_dockerfile(str, path: nil)
  set_file_for(:dockerfile, str)
  register_build_root(path) if path
end

#write_specfile(str) ⇒ Object

specfile for k8s resources spec manifest



180
181
182
# File 'lib/dklet/dsl.rb', line 180

def write_specfile(str)
  set_file_for(:specfile, str)
end