dapp 0.6.1 → 0.6.2

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.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/bin/dapp +3 -3
  3. data/config/en/common.yml +19 -4
  4. data/config/en/net_status.yml +13 -4
  5. data/lib/dapp.rb +48 -16
  6. data/lib/dapp/application.rb +75 -40
  7. data/lib/dapp/application/path.rb +3 -2
  8. data/lib/dapp/application/stages.rb +59 -0
  9. data/lib/dapp/artifact.rb +22 -0
  10. data/lib/dapp/build/stage/after_install_artifact.rb +13 -0
  11. data/lib/dapp/build/stage/after_setup_artifact.rb +17 -0
  12. data/lib/dapp/build/stage/artifact_base.rb +80 -0
  13. data/lib/dapp/build/stage/artifact_default.rb +62 -0
  14. data/lib/dapp/build/stage/base.rb +47 -12
  15. data/lib/dapp/build/stage/before_install.rb +6 -5
  16. data/lib/dapp/build/stage/before_install_artifact.rb +13 -0
  17. data/lib/dapp/build/stage/before_setup.rb +7 -8
  18. data/lib/dapp/build/stage/before_setup_artifact.rb +13 -0
  19. data/lib/dapp/build/stage/build_artifact.rb +32 -0
  20. data/lib/dapp/build/stage/docker_instructions.rb +4 -22
  21. data/lib/dapp/build/stage/from.rb +7 -8
  22. data/lib/dapp/build/stage/ga_archive.rb +1 -1
  23. data/lib/dapp/build/stage/ga_archive_dependencies.rb +1 -1
  24. data/lib/dapp/build/stage/ga_artifact_patch.rb +21 -0
  25. data/lib/dapp/build/stage/ga_base.rb +6 -29
  26. data/lib/dapp/build/stage/ga_dependencies_base.rb +4 -13
  27. data/lib/dapp/build/stage/ga_latest_patch.rb +2 -2
  28. data/lib/dapp/build/stage/import_artifact.rb +69 -0
  29. data/lib/dapp/build/stage/install/ga_post_install_patch.rb +1 -1
  30. data/lib/dapp/build/stage/install/ga_post_install_patch_dependencies.rb +1 -1
  31. data/lib/dapp/build/stage/install/ga_pre_install_patch_dependencies.rb +1 -7
  32. data/lib/dapp/build/stage/install/install.rb +12 -7
  33. data/lib/dapp/build/stage/mod/logging.rb +10 -7
  34. data/lib/dapp/build/stage/setup/chef_cookbooks.rb +3 -4
  35. data/lib/dapp/build/stage/setup/ga_post_setup_patch.rb +1 -1
  36. data/lib/dapp/build/stage/setup/ga_pre_setup_patch.rb +2 -2
  37. data/lib/dapp/build/stage/setup/ga_pre_setup_patch_dependencies.rb +2 -8
  38. data/lib/dapp/build/stage/setup/setup.rb +12 -7
  39. data/lib/dapp/builder/base.rb +13 -1
  40. data/lib/dapp/builder/chef.rb +125 -79
  41. data/lib/dapp/builder/chef/cookbook_metadata.rb +1 -1
  42. data/lib/dapp/builder/shell.rb +2 -3
  43. data/lib/dapp/cli.rb +3 -3
  44. data/lib/dapp/cli/base.rb +0 -2
  45. data/lib/dapp/cli/bp.rb +0 -4
  46. data/lib/dapp/cli/build.rb +3 -7
  47. data/lib/dapp/cli/cleanup.rb +0 -2
  48. data/lib/dapp/cli/list.rb +0 -2
  49. data/lib/dapp/cli/mrproper.rb +22 -0
  50. data/lib/dapp/cli/push.rb +4 -3
  51. data/lib/dapp/cli/run.rb +0 -2
  52. data/lib/dapp/cli/spush.rb +0 -2
  53. data/lib/dapp/cli/stage_image.rb +24 -0
  54. data/lib/dapp/cli/stages.rb +7 -5
  55. data/lib/dapp/cli/stages/cleanup_local.rb +28 -0
  56. data/lib/dapp/cli/stages/cleanup_repo.rb +24 -0
  57. data/lib/dapp/cli/stages/{flush.rb → flush_local.rb} +4 -6
  58. data/lib/dapp/cli/stages/{cleanup.rb → flush_repo.rb} +4 -6
  59. data/lib/dapp/cli/stages/pull.rb +28 -0
  60. data/lib/dapp/cli/stages/push.rb +24 -0
  61. data/lib/dapp/config/application.rb +185 -44
  62. data/lib/dapp/config/artifact.rb +10 -50
  63. data/lib/dapp/config/directive/artifact.rb +77 -0
  64. data/lib/dapp/config/directive/build_dir.rb +9 -0
  65. data/lib/dapp/config/directive/chef.rb +95 -0
  66. data/lib/dapp/config/directive/docker/artifact.rb +26 -0
  67. data/lib/dapp/config/directive/docker/base.rb +91 -0
  68. data/lib/dapp/config/directive/git_artifact.rb +59 -0
  69. data/lib/dapp/config/directive/shell/artifact.rb +38 -0
  70. data/lib/dapp/config/directive/shell/base.rb +85 -0
  71. data/lib/dapp/config/directive/tmp_dir.rb +36 -0
  72. data/lib/dapp/config/main.rb +1 -7
  73. data/lib/dapp/core_ext/hash.rb +21 -0
  74. data/lib/dapp/docker_registry/base.rb +60 -5
  75. data/lib/dapp/docker_registry/mod/request.rb +2 -14
  76. data/lib/dapp/git_artifact.rb +32 -23
  77. data/lib/dapp/git_repo/base.rb +1 -1
  78. data/lib/dapp/image/argument.rb +3 -3
  79. data/lib/dapp/image/docker.rb +13 -16
  80. data/lib/dapp/image/scratch.rb +29 -0
  81. data/lib/dapp/image/stage.rb +33 -23
  82. data/lib/dapp/lock/base.rb +18 -11
  83. data/lib/dapp/lock/file.rb +18 -16
  84. data/lib/dapp/prctl.rb +1 -0
  85. data/lib/dapp/project.rb +22 -9
  86. data/lib/dapp/project/command/bp.rb +2 -5
  87. data/lib/dapp/project/command/build.rb +1 -2
  88. data/lib/dapp/project/command/cleanup.rb +9 -7
  89. data/lib/dapp/project/command/common.rb +37 -12
  90. data/lib/dapp/project/command/mrproper.rb +57 -0
  91. data/lib/dapp/project/command/push.rb +8 -2
  92. data/lib/dapp/project/command/run.rb +1 -1
  93. data/lib/dapp/project/command/stage_image.rb +15 -0
  94. data/lib/dapp/project/command/stages/cleanup_local.rb +100 -0
  95. data/lib/dapp/project/command/stages/cleanup_repo.rb +65 -0
  96. data/lib/dapp/project/command/stages/common.rb +48 -0
  97. data/lib/dapp/project/command/stages/flush_local.rb +24 -0
  98. data/lib/dapp/project/command/stages/flush_repo.rb +22 -0
  99. data/lib/dapp/project/command/stages/pull.rb +26 -0
  100. data/lib/dapp/project/command/stages/push.rb +22 -0
  101. data/lib/dapp/project/dappfile.rb +3 -1
  102. data/lib/dapp/project/deps/base.rb +52 -0
  103. data/lib/dapp/project/deps/gitartifact.rb +36 -0
  104. data/lib/dapp/project/lock.rb +20 -13
  105. data/lib/dapp/project/logging/base.rb +20 -3
  106. data/lib/dapp/project/logging/i18n.rb +25 -0
  107. data/lib/dapp/project/logging/paint.rb +47 -0
  108. data/lib/dapp/project/logging/process.rb +17 -10
  109. data/lib/dapp/project/shellout/base.rb +74 -0
  110. data/lib/dapp/project/shellout/streaming.rb +49 -0
  111. data/lib/dapp/project/shellout/system.rb +72 -0
  112. data/lib/dapp/project/ssh_agent.rb +8 -9
  113. data/lib/dapp/version.rb +1 -1
  114. metadata +48 -17
  115. data/lib/dapp/build/stage/artifact.rb +0 -40
  116. data/lib/dapp/build/stage/mod/artifact.rb +0 -79
  117. data/lib/dapp/config/chef.rb +0 -51
  118. data/lib/dapp/config/docker.rb +0 -82
  119. data/lib/dapp/config/git_artifact.rb +0 -51
  120. data/lib/dapp/config/shell.rb +0 -64
  121. data/lib/dapp/helper/i18n.rb +0 -20
  122. data/lib/dapp/helper/paint.rb +0 -27
  123. data/lib/dapp/helper/shellout.rb +0 -63
  124. data/lib/dapp/helper/streaming.rb +0 -47
  125. data/lib/dapp/project/command/stages_cleanup.rb +0 -72
  126. data/lib/dapp/project/command/stages_flush.rb +0 -20
  127. data/lib/dapp/project/paint.rb +0 -16
@@ -19,7 +19,7 @@ module Dapp
19
19
  end
20
20
 
21
21
  def depends(dependency, *_a, &_blk)
22
- @cookbook_metadata.depends << dependency
22
+ @cookbook_metadata.depends << dependency.to_s
23
23
  end
24
24
 
25
25
  # rubocop:disable Style/MethodMissing
@@ -2,15 +2,14 @@ module Dapp
2
2
  module Builder
3
3
  # Shell
4
4
  class Shell < Base
5
- [:before_install, :before_setup, :install, :setup].each do |stage|
5
+ [:before_install, :before_setup, :install, :setup, :build_artifact].each do |stage|
6
6
  define_method("#{stage}_checksum") do
7
7
  [application.config._shell.public_send("_#{stage}"),
8
8
  application.config._shell.public_send("_#{stage}_cache_version")].flatten
9
9
  end
10
10
  define_method("#{stage}?") { !stage_empty?(stage) }
11
11
  define_method(stage.to_s) do |image|
12
- image.add_command("export DAPP_BUILD_STAGE=#{stage}",
13
- *stage_commands(stage)) unless stage_empty?(stage)
12
+ image.add_command(*stage_commands(stage)) unless stage_empty?(stage)
14
13
  end
15
14
  end
16
15
 
@@ -1,5 +1,3 @@
1
- require 'mixlib/cli'
2
-
3
1
  module Dapp
4
2
  # CLI
5
3
  class CLI
@@ -7,7 +5,7 @@ module Dapp
7
5
  include Mixlib::CLI
8
6
  include Helper::Trivia
9
7
 
10
- SUBCOMMANDS = %w(build push spush list run stages cleanup bp).freeze
8
+ SUBCOMMANDS = ['build', 'push', 'spush', 'list', 'run', 'stages', 'cleanup', 'bp', 'mrproper', 'stage image'].freeze
11
9
 
12
10
  banner <<BANNER.freeze
13
11
  Usage: dapp [options] sub-command [sub-command options]
@@ -21,6 +19,8 @@ dapp spush [options] [APPS PATTERN ...] REPO
21
19
  dapp list [options] [APPS PATTERN ...]
22
20
  dapp run [options] [APP PATTERN] [DOCKER ARGS]
23
21
  dapp cleanup [options] [APPS PATTERN ...]
22
+ dapp mrproper [options]
23
+ dapp stage image [options] [APP PATTERN]
24
24
  dapp stages
25
25
 
26
26
  Options:
@@ -1,5 +1,3 @@
1
- require 'mixlib/cli'
2
-
3
1
  module Dapp
4
2
  class CLI
5
3
  # Base of CLI subcommands
@@ -1,11 +1,7 @@
1
- require 'mixlib/cli'
2
-
3
1
  module Dapp
4
2
  class CLI
5
3
  # CLI bp subcommand
6
4
  class Bp < Push
7
- include Dapp::Helper::Shellout
8
-
9
5
  banner <<BANNER.freeze
10
6
  Version: #{Dapp::VERSION}
11
7
 
@@ -1,11 +1,7 @@
1
- require 'mixlib/cli'
2
-
3
1
  module Dapp
4
2
  class CLI
5
3
  # CLI build subcommand
6
4
  class Build < Base
7
- include Dapp::Helper::Shellout
8
-
9
5
  banner <<BANNER.freeze
10
6
  Version: #{Dapp::VERSION}
11
7
 
@@ -42,9 +38,9 @@ BANNER
42
38
  option :introspect_stage,
43
39
  long: '--introspect-stage STAGE',
44
40
  proc: proc { |v| v.to_sym },
45
- in: [nil, :from, :before_install, :g_a_archive, :g_a_pre_install_patch, :install, :g_a_post_install_patch,
46
- :artifact, :before_setup, :g_a_pre_setup_patch, :chef_cookbooks, :setup, :g_a_post_setup_patch,
47
- :g_a_latest_patch, :docker_instructions]
41
+ in: [nil, :from, :before_install, :before_install_artifact, :g_a_archive, :g_a_pre_install_patch, :install,
42
+ :g_a_post_install_patch, :after_install_artifact, :before_setup, :before_setup_artifact, :g_a_pre_setup_patch,
43
+ :chef_cookbooks, :setup, :g_a_post_setup_patch, :after_setup_artifact, :g_a_latest_patch, :docker_instructions]
48
44
 
49
45
  option :ssh_key,
50
46
  long: '--ssh-key SSH_KEY',
@@ -1,5 +1,3 @@
1
- require 'mixlib/cli'
2
-
3
1
  module Dapp
4
2
  class CLI
5
3
  # Cleanup subcommand
@@ -1,5 +1,3 @@
1
- require 'mixlib/cli'
2
-
3
1
  module Dapp
4
2
  class CLI
5
3
  # CLI list subcommand
@@ -0,0 +1,22 @@
1
+ module Dapp
2
+ class CLI
3
+ # CLI mrprooper subcommand
4
+ class Mrproper < Base
5
+ banner <<BANNER.freeze
6
+ Version: #{Dapp::VERSION}
7
+
8
+ Usage:
9
+ dapp mrprooper [options]
10
+
11
+ Options:
12
+ BANNER
13
+ option :proper_all,
14
+ long: '--all',
15
+ boolean: true
16
+
17
+ option :proper_cache_version,
18
+ long: '--improper-cache-version-stages',
19
+ boolean: true
20
+ end
21
+ end
22
+ end
@@ -1,5 +1,3 @@
1
- require 'mixlib/cli'
2
-
3
1
  module Dapp
4
2
  class CLI
5
3
  # CLI push subcommand
@@ -11,7 +9,6 @@ Usage:
11
9
  dapp push [options] [APP PATTERN] REPO
12
10
 
13
11
  APP PATTERN Applications to process [default: *].
14
- REPO Pushed image name.
15
12
 
16
13
  Options:
17
14
  BANNER
@@ -50,6 +47,10 @@ BANNER
50
47
  description: 'Tag by git commit',
51
48
  boolean: true
52
49
 
50
+ option :with_stages,
51
+ long: '--with-stages',
52
+ boolean: true
53
+
53
54
  def run(argv = ARGV)
54
55
  self.class.parse_options(self, argv)
55
56
  repo = self.class.required_argument(self)
@@ -1,5 +1,3 @@
1
- require 'mixlib/cli'
2
-
3
1
  module Dapp
4
2
  class CLI
5
3
  # CLI run subcommand
@@ -1,5 +1,3 @@
1
- require 'mixlib/cli'
2
-
3
1
  module Dapp
4
2
  class CLI
5
3
  # CLI spush subcommand
@@ -0,0 +1,24 @@
1
+ module Dapp
2
+ class CLI
3
+ # CLI stage image subcommand
4
+ class StageImage < Base
5
+ banner <<BANNER.freeze
6
+ Version: #{Dapp::VERSION}
7
+
8
+ Usage:
9
+ dapp stage image [options] [APP PATTERN ...]
10
+
11
+ APP PATTERN Application to process [default: *].
12
+
13
+ Options:
14
+ BANNER
15
+ option :stage,
16
+ long: '--stage STAGE',
17
+ proc: proc { |v| v.to_sym },
18
+ default: :docker_instructions,
19
+ in: [:from, :before_install, :before_install_artifact, :g_a_archive, :g_a_pre_install_patch, :install,
20
+ :g_a_post_install_patch, :after_install_artifact, :before_setup, :before_setup_artifact, :g_a_pre_setup_patch,
21
+ :chef_cookbooks, :setup, :g_a_post_setup_patch, :after_setup_artifact, :g_a_latest_patch, :docker_instructions]
22
+ end
23
+ end
24
+ end
@@ -1,18 +1,20 @@
1
- require 'mixlib/cli'
2
-
3
1
  module Dapp
4
2
  class CLI
5
3
  # CLI stages subcommand
6
4
  class Stages < CLI
7
- SUBCOMMANDS = %w(flush cleanup).freeze
5
+ SUBCOMMANDS = ['flush local', 'flush repo', 'cleanup local', 'cleanup repo', 'push', 'pull'].freeze
8
6
 
9
7
  banner <<BANNER.freeze
10
8
  Version: #{Dapp::VERSION}
11
9
 
12
10
  Available subcommands: (for details, dapp SUB-COMMAND --help)
13
11
 
14
- dapp stages flush
15
- dapp stages cleanup
12
+ dapp stages cleanup local
13
+ dapp stages cleanup repo
14
+ dapp stages flush local
15
+ dapp stages flush repo
16
+ dapp stages push
17
+ dapp stages pull
16
18
 
17
19
  Options:
18
20
  BANNER
@@ -0,0 +1,28 @@
1
+ module Dapp
2
+ class CLI
3
+ class Stages
4
+ # stages cleanup local subcommand
5
+ class CleanupLocal < Base
6
+ banner <<BANNER.freeze
7
+ Version: #{Dapp::VERSION}
8
+
9
+ Usage:
10
+ dapp stages cleanup local [options] [APPS PATTERN ...] REPO
11
+
12
+ APPS PATTERN Applications to process [default: *].
13
+
14
+ Options:
15
+ BANNER
16
+ option :proper_cache_version,
17
+ long: '--improper-cache-version',
18
+ boolean: true
19
+
20
+ def run(argv = ARGV)
21
+ self.class.parse_options(self, argv)
22
+ repo = self.class.required_argument(self)
23
+ Project.new(cli_options: config, apps_patterns: cli_arguments).stages_cleanup_local(repo)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ module Dapp
2
+ class CLI
3
+ class Stages
4
+ # stages cleanup repo subcommand
5
+ class CleanupRepo < CleanupLocal
6
+ banner <<BANNER.freeze
7
+ Version: #{Dapp::VERSION}
8
+
9
+ Usage:
10
+ dapp stages cleanup repo [options] [APPS PATTERN ...] REPO
11
+
12
+ APPS PATTERN Applications to process [default: *].
13
+
14
+ Options:
15
+ BANNER
16
+ def run(argv = ARGV)
17
+ self.class.parse_options(self, argv)
18
+ repo = self.class.required_argument(self)
19
+ Project.new(cli_options: config, apps_patterns: cli_arguments).stages_cleanup_repo(repo)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,15 +1,13 @@
1
- require 'mixlib/cli'
2
-
3
1
  module Dapp
4
2
  class CLI
5
3
  class Stages
6
- # stages flush subcommand
7
- class Flush < Base
4
+ # stages flush local subcommand
5
+ class FlushLocal < Base
8
6
  banner <<BANNER.freeze
9
7
  Version: #{Dapp::VERSION}
10
8
 
11
9
  Usage:
12
- dapp stages flush [options] [APPS PATTERN ...]
10
+ dapp stages flush local [options] [APPS PATTERN ...]
13
11
 
14
12
  APPS PATTERN Applications to process [default: *].
15
13
 
@@ -17,7 +15,7 @@ Options:
17
15
  BANNER
18
16
  def run(argv = ARGV)
19
17
  self.class.parse_options(self, argv)
20
- Project.new(cli_options: config, apps_patterns: cli_arguments).stages_flush
18
+ Project.new(cli_options: config, apps_patterns: cli_arguments).stages_flush_local
21
19
  end
22
20
  end
23
21
  end
@@ -1,15 +1,13 @@
1
- require 'mixlib/cli'
2
-
3
1
  module Dapp
4
2
  class CLI
5
3
  class Stages
6
- # stages cleanup subcommand
7
- class Cleanup < Base
4
+ # stages flush repo subcommand
5
+ class FlushRepo < Base
8
6
  banner <<BANNER.freeze
9
7
  Version: #{Dapp::VERSION}
10
8
 
11
9
  Usage:
12
- dapp stages cleanup [options] [APPS PATTERN ...] [REPO]
10
+ dapp stages flush repo [options] [APPS PATTERN ...] REPO
13
11
 
14
12
  APPS PATTERN Applications to process [default: *].
15
13
 
@@ -18,7 +16,7 @@ BANNER
18
16
  def run(argv = ARGV)
19
17
  self.class.parse_options(self, argv)
20
18
  repo = self.class.required_argument(self)
21
- Project.new(cli_options: config, apps_patterns: cli_arguments).stages_cleanup(repo)
19
+ Project.new(cli_options: config, apps_patterns: cli_arguments).stages_flush_repo(repo)
22
20
  end
23
21
  end
24
22
  end
@@ -0,0 +1,28 @@
1
+ module Dapp
2
+ class CLI
3
+ class Stages
4
+ # stages pull subcommand
5
+ class Pull < Base
6
+ banner <<BANNER.freeze
7
+ Version: #{Dapp::VERSION}
8
+
9
+ Usage:
10
+ dapp stages pull [options] [APP PATTERN] REPO
11
+
12
+ APP PATTERN Applications to process [default: *].
13
+
14
+ Options:
15
+ BANNER
16
+ option :pull_all_stages,
17
+ long: '--all',
18
+ boolean: true
19
+
20
+ def run(argv = ARGV)
21
+ self.class.parse_options(self, argv)
22
+ repo = self.class.required_argument(self)
23
+ Project.new(cli_options: config, apps_patterns: cli_arguments).stages_pull(repo)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ module Dapp
2
+ class CLI
3
+ class Stages
4
+ # stages push subcommand
5
+ class Push < Base
6
+ banner <<BANNER.freeze
7
+ Version: #{Dapp::VERSION}
8
+
9
+ Usage:
10
+ dapp stages push [options] [APP PATTERN] REPO
11
+
12
+ APP PATTERN Applications to process [default: *].
13
+
14
+ Options:
15
+ BANNER
16
+ def run(argv = ARGV)
17
+ self.class.parse_options(self, argv)
18
+ repo = self.class.required_argument(self)
19
+ Project.new(cli_options: config, apps_patterns: cli_arguments).stages_push(repo)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -2,26 +2,36 @@ module Dapp
2
2
  module Config
3
3
  # Application
4
4
  class Application
5
- attr_reader :_builder
6
5
  attr_reader :_home_path
7
6
  attr_reader :_basename
7
+ attr_reader :_parent
8
+ attr_reader :_builder, :_chef, :_shell
9
+ attr_reader :_install_dependencies, :_setup_dependencies
8
10
  attr_reader :_docker
9
11
  attr_reader :_git_artifact
10
- attr_reader :_artifact
11
- attr_reader :_chef
12
- attr_reader :_shell
13
- attr_reader :_parent
14
- attr_reader :_install_dependencies
15
- attr_reader :_setup_dependencies
16
- attr_reader :_parent
12
+ attr_reader :_before_install_artifact, :_before_setup_artifact, :_after_install_artifact, :_after_setup_artifact, :_import_artifact
13
+ attr_reader :_tmp_dir, :_build_dir
17
14
 
18
15
  def initialize(parent)
19
- @_apps = []
20
16
  @_parent = parent
21
17
 
22
- @_artifact = []
23
- @_install_dependencies = []
24
- @_setup_dependencies = []
18
+ @_docker = Directive::Docker::Base.new
19
+ @_git_artifact = Directive::GitArtifact.new
20
+ @_shell = Directive::Shell::Base.new
21
+ @_chef = Directive::Chef.new
22
+ @_tmp_dir = Directive::TmpDir.new
23
+ @_build_dir = Directive::BuildDir.new
24
+
25
+ @_apps = []
26
+
27
+ @_before_install_artifact = []
28
+ @_before_setup_artifact = []
29
+ @_after_install_artifact = []
30
+ @_after_setup_artifact = []
31
+ @_import_artifact = []
32
+
33
+ @_install_dependencies = []
34
+ @_setup_dependencies = []
25
35
 
26
36
  yield self if block_given?
27
37
  end
@@ -35,40 +45,40 @@ module Dapp
35
45
  end
36
46
 
37
47
  def builder(type)
38
- project.log_warning(desc: { code: 'excess_builder_instruction', context: 'warning' }) if @_chef.empty? && @_shell.empty?
48
+ project.log_warning(desc: { code: 'excess_builder_instruction', context: 'warning' }) if @_chef.send(:empty?) && @_shell.send(:empty?)
39
49
  raise Error::Config, code: :builder_type_unsupported, data: { type: type } unless [:chef, :shell].include?((type = type.to_sym))
40
50
  another_builder = [:chef, :shell].find { |t| t != type }
41
- instance_variable_set(:"@_#{another_builder}", Config.const_get(another_builder.capitalize).new)
51
+ instance_variable_set(:"@_#{another_builder}", instance_variable_get(:"@_#{another_builder}").class.new)
42
52
  @_builder = type
43
53
  end
44
54
 
45
55
  def chef
46
- raise Error::Config, code: :builder_type_conflict unless _builder == :chef
47
- @_chef ||= Chef.new
56
+ @_chef.tap { raise Error::Config, code: :builder_type_conflict unless _builder == :chef }
48
57
  end
49
58
 
50
59
  def shell
51
- raise Error::Config, code: :builder_type_conflict unless _builder == :shell
52
- @_shell ||= Shell.new
60
+ @_shell.tap { raise Error::Config, code: :builder_type_conflict unless _builder == :shell }
53
61
  end
54
62
 
55
63
  def docker
56
- @_docker ||= Docker.new
64
+ @_docker
57
65
  end
58
66
 
59
- def artifact(where_to_add, **options, &blk)
60
- @_artifact << begin
61
- config = clone.tap do |app|
62
- app.instance_variable_set(:'@_artifact', [])
63
- app.instance_variable_set(:'@_name', app_name("artifact-#{SecureRandom.hex(2)}"))
64
- app.instance_eval(&blk) if block_given?
65
- end
66
- Artifact::Stage.new(where_to_add, config: config, **options)
67
- end
67
+ def artifact(where_to_add, before: nil, after: nil, **options, &blk)
68
+ raise Error::Config, code: :stage_artifact_double_associate unless before.nil? || after.nil?
69
+ artifact_base(instance_variable_get(:"@_#{artifact_variable_name(before, after)}"), where_to_add, **options, &blk)
68
70
  end
69
71
 
70
72
  def git_artifact
71
- @_git_artifact ||= GitArtifact.new
73
+ @_git_artifact ||= Directive::GitArtifact.new
74
+ end
75
+
76
+ def tmp_dir
77
+ @_tmp_dir
78
+ end
79
+
80
+ def build_dir
81
+ @_build_dir
72
82
  end
73
83
 
74
84
  def _name
@@ -103,28 +113,37 @@ module Dapp
103
113
 
104
114
  attr_accessor :project
105
115
 
106
- private
116
+ def clone_to_application
117
+ clone_to(Application.new(self))
118
+ end
119
+
120
+ def clone_to_artifact
121
+ clone_to(Artifact.new(self))
122
+ end
107
123
 
108
124
  # rubocop:disable Metrics/AbcSize
109
- def clone
110
- Application.new(self).tap do |app|
111
- app.instance_variable_set(:'@project', project)
112
- app.instance_variable_set(:'@_builder', _builder)
113
- app.instance_variable_set(:'@_home_path', _home_path)
114
- app.instance_variable_set(:'@_basename', _basename)
115
- app.instance_variable_set(:'@_install_dependencies', _install_dependencies)
116
- app.instance_variable_set(:'@_setup_dependencies', _setup_dependencies)
117
- app.instance_variable_set(:'@_artifact', Marshal.load(Marshal.dump(_artifact)))
118
- app.instance_variable_set(:'@_docker', _docker.clone) unless @_docker.nil?
119
- app.instance_variable_set(:'@_git_artifact', _git_artifact.clone) unless @_git_artifact.nil?
120
- app.instance_variable_set(:'@_chef', _chef.clone) unless @_chef.nil?
121
- app.instance_variable_set(:'@_shell', _shell.clone) unless @_shell.nil?
125
+ def clone_to(app)
126
+ app.instance_variable_set(:'@project', project)
127
+ app.instance_variable_set(:'@_builder', _builder)
128
+ app.instance_variable_set(:'@_home_path', _home_path)
129
+ app.instance_variable_set(:'@_basename', _basename)
130
+ app.instance_variable_set(:'@_install_dependencies', _install_dependencies)
131
+ app.instance_variable_set(:'@_setup_dependencies', _setup_dependencies)
132
+ [:_before_install_artifact, :_before_setup_artifact, :_after_install_artifact, :_after_setup_artifact, :_import_artifact].each do |artifact|
133
+ app.instance_variable_set(:"@#{artifact}", instance_variable_get(:"@#{artifact}").map { |a| a.send(:clone) })
122
134
  end
135
+ app.instance_variable_set(:'@_docker', _docker.send(:clone))
136
+ app.instance_variable_set(:'@_git_artifact', _git_artifact.send(:clone))
137
+ app.instance_variable_set(:'@_chef', _chef.send(:clone))
138
+ app.instance_variable_set(:'@_shell', _shell.send(:clone))
139
+ app.instance_variable_set(:'@_tmp_dir', _tmp_dir.send(:clone))
140
+ app.instance_variable_set(:'@_build_dir', _build_dir.send(:clone))
141
+ app
123
142
  end
124
143
  # rubocop:enable Metrics/AbcSize
125
144
 
126
145
  def app(sub_name, &blk)
127
- clone.tap do |app|
146
+ clone_to_application.tap do |app|
128
147
  app.instance_variable_set(:'@_name', app_name(sub_name))
129
148
  app.instance_eval(&blk) if block_given?
130
149
  @_apps += app._apps
@@ -134,6 +153,128 @@ module Dapp
134
153
  def app_name(sub_name)
135
154
  [_name, sub_name].compact.join('-')
136
155
  end
156
+
157
+ def artifact_variable_name(before, after)
158
+ return :import_artifact if before.nil? && after.nil?
159
+
160
+ if before.nil?
161
+ prefix = :after
162
+ stage = after
163
+ else
164
+ prefix = :before
165
+ stage = before
166
+ end
167
+
168
+ return [prefix, stage, :artifact].join('_') if [:install, :setup].include?(stage.to_sym)
169
+ raise Error::Config, code: :stage_artifact_not_supported_associated_stage, data: { stage: stage }
170
+ end
171
+
172
+ def artifact_base(artifact, where_to_add, **options, &blk)
173
+ artifact << begin
174
+ config = clone_to_artifact.tap do |app|
175
+ app.instance_variable_set(:'@_shell', _shell.send(:clone_to_artifact))
176
+ app.instance_variable_set(:'@_docker', _docker.send(:clone_to_artifact))
177
+ app.instance_variable_set(:'@_name', app_name("artifact-#{SecureRandom.hex(2)}"))
178
+ app.instance_eval(&blk) if block_given?
179
+ end
180
+ Directive::Artifact::Stage.new(where_to_add, config: config, **options)
181
+ end
182
+ end
183
+
184
+ def validate!
185
+ if _docker._from.nil?
186
+ validate_scratch_directives!
187
+ validate_scratch_artifacts!
188
+ else
189
+ raise Error::Config, code: :stage_artifact_not_associated unless _import_artifact.empty?
190
+ end
191
+ validate_artifacts!
192
+ validate_artifacts_artifacts!
193
+ end
194
+
195
+ def validate_scratch_directives!
196
+ raise Error::Config, code: :scratch_unsupported_directive, data: { directive: :app } unless _apps.length == 1
197
+
198
+ directives = [:_shell, :_chef, :_git_artifact, :_install_dependencies, :_setup_dependencies, :_tmp_dir, :_build_dir]
199
+ directives.each do |directive|
200
+ raise Error::Config,
201
+ code: :scratch_unsupported_directive,
202
+ data: { directive: directive[1..-1] } unless public_send(directive).send(:empty?)
203
+ end
204
+
205
+ docker_directives = [:_expose, :_env, :_cmd, :_onbuild, :_workdir, :_user, :_entrypoint]
206
+ docker_directives.each do |directive|
207
+ value = _docker.public_send(directive)
208
+ raise Error::Config,
209
+ code: :scratch_unsupported_directive,
210
+ data: { directive: "docker.#{directive[1..-1]}" } unless value.nil? || value.send(:empty?)
211
+ end
212
+ end
213
+
214
+ def validate_scratch_artifacts!
215
+ raise Error::Config, code: :scratch_artifact_associated unless associated_artifacts.empty?
216
+ raise Error::Config, code: :scratch_artifact_required if _import_artifact.empty?
217
+ _import_artifact.each do |artifact|
218
+ raise Error::Config, code: :scratch_artifact_docker_from if artifact._config._docker._from.nil?
219
+ end
220
+ end
221
+
222
+ def validate_artifacts_artifacts!
223
+ associated_artifacts.each { |artifact| artifact._config.validate! }
224
+ end
225
+
226
+ def associated_artifacts
227
+ _before_install_artifact + _before_setup_artifact + _after_install_artifact + _after_setup_artifact
228
+ end
229
+
230
+ def validate_artifacts!
231
+ artifacts = validate_artifact_format(associated_artifacts + _import_artifact + _git_artifact._remote + _git_artifact._local)
232
+ loop do
233
+ break if artifacts.empty?
234
+ verifiable_artifact = artifacts.shift
235
+ artifacts.select { |artifact| artifact[:where_to_add] == verifiable_artifact[:where_to_add] }.each do |artifact|
236
+ next if verifiable_artifact[:index] == artifact[:index]
237
+ validate_artifact!(verifiable_artifact, artifact)
238
+ validate_artifact!(artifact, verifiable_artifact)
239
+ end
240
+ end
241
+ end
242
+
243
+ def validate_artifact_format(artifacts)
244
+ artifacts.map do |a|
245
+ path_format = proc { |path| File.expand_path(File.join('/', path, '/'))[1..-1] }
246
+
247
+ path_format.call(a._where_to_add) =~ %r{^([^\/]*)\/?(.*)$}
248
+ where_to_add = Regexp.last_match(1)
249
+ includes = a._paths
250
+ includes << Regexp.last_match(2) unless Regexp.last_match(2).empty?
251
+ excludes = a._exclude_paths
252
+
253
+ {
254
+ index: artifacts.index(a),
255
+ where_to_add: where_to_add,
256
+ includes: includes.map(&path_format),
257
+ excludes: excludes.map(&path_format)
258
+ }
259
+ end
260
+ end
261
+
262
+ def validate_artifact!(verifiable_artifact, artifact)
263
+ verifiable_artifact[:includes].each do |verifiable_path|
264
+ potential_conflicts = artifact[:includes].select { |path| path.start_with?(verifiable_path) }
265
+ validate_artifact_path!(verifiable_artifact, potential_conflicts)
266
+ end.empty? && verifiable_artifact[:excludes].empty? && raise(Error::Config, code: :artifact_conflict)
267
+ validate_artifact_path!(verifiable_artifact, artifact[:includes]) if verifiable_artifact[:includes].empty?
268
+ end
269
+
270
+ def validate_artifact_path!(verifiable_artifact, potential_conflicts)
271
+ potential_conflicts.all? do |path|
272
+ loop do
273
+ break if verifiable_artifact[:excludes].include?(path) || ((path = File.dirname(path)) == '.')
274
+ end
275
+ verifiable_artifact[:excludes].include?(path)
276
+ end.tap { |res| res || raise(Error::Config, code: :artifact_conflict) }
277
+ end
137
278
  end
138
279
  end
139
280
  end