djin 0.11.3 → 0.11.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/Dockerfile +5 -1
- data/Gemfile.lock +2 -2
- data/README.md +10 -10
- data/djin.yml +1 -1
- data/docker-entrypoint.sh +2 -0
- data/examples/djin.yml +1 -1
- data/examples/djin_lib/test.yml +1 -1
- data/examples/local_tasks/djin.yml +1 -1
- data/examples/remote_tasks/djin.yml +1 -1
- data/lib/djin.rb +4 -2
- data/lib/djin/config_loader.rb +17 -29
- data/lib/djin/errors.rb +10 -0
- data/lib/djin/{include_resolver.rb → include_config_loader.rb} +26 -4
- data/lib/djin/include_contract.rb +29 -0
- data/lib/djin/interpreter.rb +1 -7
- data/lib/djin/version.rb +1 -1
- data/wait-for-it.sh +183 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20d3e4379f1a66394b34708a76c8c362b4ce996bea8fba4a449856260533c288
|
4
|
+
data.tar.gz: e6d6713bc9a6a81f7bdc34ae56a75fc962a6c0c76719747c044e9557f8ff6f42
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e809bb84de4f96ad4054e07020460502b6fded297074356d2255b649298986c06881f1719946e7fd3731bccf6d6f23cb2b6c0597a9255a629837028e9866eb1
|
7
|
+
data.tar.gz: ddb2334bfa660b5114bf8dd5eb83c3aebcedd32087bf880f616e5630e6259c34ad2e9c264cc0c8e2ce04fd9d3b05ad5d89b89c212059cc71ce40007837a47838
|
data/CHANGELOG.md
CHANGED
data/Dockerfile
CHANGED
@@ -2,6 +2,7 @@ ARG RUBY_VERSION
|
|
2
2
|
FROM ruby:${RUBY_VERSION:-2.6.5}-alpine AS builder
|
3
3
|
|
4
4
|
ENV BUILD_PACKAGES build-base git
|
5
|
+
ENV DEV_PACKAGES bash
|
5
6
|
|
6
7
|
RUN mkdir /bundle
|
7
8
|
|
@@ -20,6 +21,9 @@ RUN bundle install
|
|
20
21
|
|
21
22
|
FROM builder AS dev
|
22
23
|
|
24
|
+
RUN apk add $DEV_PACKAGES && \
|
25
|
+
rm -rf /var/cache/apk/*
|
26
|
+
|
23
27
|
WORKDIR /usr/src/djin
|
24
28
|
|
25
29
|
COPY . .
|
@@ -45,4 +49,4 @@ RUN rake install
|
|
45
49
|
|
46
50
|
WORKDIR /usr/src/project
|
47
51
|
|
48
|
-
ENTRYPOINT ["/usr/src/
|
52
|
+
ENTRYPOINT ["/usr/src/djin/docker-entrypoint.sh"]
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
djin (0.11.
|
4
|
+
djin (0.11.4)
|
5
5
|
dry-cli (~> 0.6.0)
|
6
6
|
dry-equalizer (~> 0.3.0)
|
7
7
|
dry-struct (~> 1.3.0)
|
@@ -40,7 +40,7 @@ GEM
|
|
40
40
|
dry-logic (1.1.0)
|
41
41
|
concurrent-ruby (~> 1.0)
|
42
42
|
dry-core (~> 0.5, >= 0.5)
|
43
|
-
dry-schema (1.6.
|
43
|
+
dry-schema (1.6.1)
|
44
44
|
concurrent-ruby (~> 1.0)
|
45
45
|
dry-configurable (~> 0.8, >= 0.8.3)
|
46
46
|
dry-core (~> 0.5, >= 0.5)
|
data/README.md
CHANGED
@@ -27,7 +27,7 @@ If you use Rbenv you can install djin only once and create an alias in your .bas
|
|
27
27
|
To use djin first you need to create a djin.yml file:
|
28
28
|
|
29
29
|
```yaml
|
30
|
-
djin_version: '0.11.
|
30
|
+
djin_version: '0.11.4'
|
31
31
|
|
32
32
|
tasks:
|
33
33
|
# With a docker image
|
@@ -54,7 +54,7 @@ You can also set task dependencies with depends_on option:
|
|
54
54
|
|
55
55
|
|
56
56
|
```yaml
|
57
|
-
djin_version: '0.11.
|
57
|
+
djin_version: '0.11.4'
|
58
58
|
|
59
59
|
_default_run_options: &default_run_options
|
60
60
|
options: "--rm"
|
@@ -83,7 +83,7 @@ tasks:
|
|
83
83
|
Or mix local commands and docker/docker-compose commands:
|
84
84
|
|
85
85
|
```yaml
|
86
|
-
djin_version: '0.11.
|
86
|
+
djin_version: '0.11.4'
|
87
87
|
|
88
88
|
_default_run_options: &default_run_options
|
89
89
|
options: "--rm"
|
@@ -122,7 +122,7 @@ After that you can run `djin {{task_name}}`, like `djin script` or `djin test`
|
|
122
122
|
You can also use environment variables using the '{{YOUR_ENV_HERE}}' syntax, like so:
|
123
123
|
|
124
124
|
```yaml
|
125
|
-
djin_version: '0.11.
|
125
|
+
djin_version: '0.11.4'
|
126
126
|
|
127
127
|
_default_run_options: &default_run_options
|
128
128
|
options: "--rm"
|
@@ -139,7 +139,7 @@ tasks:
|
|
139
139
|
|
140
140
|
Or define some variables to use in multiple locations
|
141
141
|
```yaml
|
142
|
-
djin_version: '0.11.
|
142
|
+
djin_version: '0.11.4'
|
143
143
|
|
144
144
|
_default_run_options: &default_run_options
|
145
145
|
options: "--rm"
|
@@ -163,7 +163,7 @@ tasks:
|
|
163
163
|
It's also possible to pass custom arguments to the command, which means is possible to make a djin task act like the command itself:
|
164
164
|
|
165
165
|
```yaml
|
166
|
-
djin_version: '0.11.
|
166
|
+
djin_version: '0.11.4'
|
167
167
|
|
168
168
|
_default_run_options: &default_run_options
|
169
169
|
options: "--rm"
|
@@ -189,7 +189,7 @@ Under the hood djin uses [Mustache](https://mustache.github.io/), so you can use
|
|
189
189
|
If you have multiple tasks with similar behavior and with small differences you can use the `include` keyword, so this:
|
190
190
|
|
191
191
|
```yaml
|
192
|
-
djin_version: '0.11.
|
192
|
+
djin_version: '0.11.4'
|
193
193
|
|
194
194
|
tasks:
|
195
195
|
"host1:ssh":
|
@@ -228,7 +228,7 @@ can become this:
|
|
228
228
|
|
229
229
|
```yaml
|
230
230
|
# djin.yml
|
231
|
-
djin_version: '0.11.
|
231
|
+
djin_version: '0.11.4'
|
232
232
|
|
233
233
|
include:
|
234
234
|
- file: '.djin/server_tasks.yml'
|
@@ -250,7 +250,7 @@ include:
|
|
250
250
|
|
251
251
|
```yaml
|
252
252
|
# .djin/server_tasks.yml
|
253
|
-
djin_version: '0.11.
|
253
|
+
djin_version: '0.11.4'
|
254
254
|
|
255
255
|
tasks:
|
256
256
|
"{{namespace}}:ssh":
|
@@ -272,7 +272,7 @@ tasks:
|
|
272
272
|
You can also reuse tasks in some git repository, to do that you need to declare a git source and optionally a version:
|
273
273
|
|
274
274
|
```yaml
|
275
|
-
djin_version: '0.11.
|
275
|
+
djin_version: '0.11.4'
|
276
276
|
|
277
277
|
include:
|
278
278
|
- git: 'https://github.com/catks/djin.git'
|
data/djin.yml
CHANGED
data/docker-entrypoint.sh
CHANGED
data/examples/djin.yml
CHANGED
data/examples/djin_lib/test.yml
CHANGED
data/lib/djin.rb
CHANGED
@@ -10,18 +10,20 @@ require 'dry/cli'
|
|
10
10
|
require 'mustache'
|
11
11
|
require 'optparse'
|
12
12
|
require 'git'
|
13
|
+
require 'djin/errors'
|
13
14
|
require 'djin/extensions/hash_extensions'
|
14
15
|
require 'djin/extensions/object_extensions'
|
15
16
|
require 'djin/entities/types'
|
16
17
|
require 'djin/entities/task'
|
17
18
|
require 'djin/entities/include_config.rb'
|
18
19
|
require 'djin/entities/main_config'
|
20
|
+
require 'djin/include_contract'
|
19
21
|
require 'djin/interpreter/base_command_builder'
|
20
22
|
require 'djin/interpreter/docker_command_builder'
|
21
23
|
require 'djin/interpreter/docker_compose_command_builder'
|
22
24
|
require 'djin/interpreter/local_command_builder'
|
23
25
|
require 'djin/interpreter'
|
24
|
-
require 'djin/
|
26
|
+
require 'djin/include_config_loader'
|
25
27
|
require 'djin/config_loader'
|
26
28
|
require 'djin/executor'
|
27
29
|
require 'djin/root_cli_parser'
|
@@ -51,7 +53,7 @@ module Djin
|
|
51
53
|
@remote_config_repository = RemoteConfigRepository.new(remote_configs)
|
52
54
|
|
53
55
|
CLI.load_tasks!(tasks)
|
54
|
-
rescue Djin::
|
56
|
+
rescue Djin::InvalidConfigurationError => e
|
55
57
|
error_name = e.class.name.split('::').last
|
56
58
|
abort("[#{error_name}] #{e.message}")
|
57
59
|
end
|
data/lib/djin/config_loader.rb
CHANGED
@@ -1,36 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Djin
|
4
|
-
# TODO: Refactor this class to
|
5
|
-
#
|
6
|
-
#
|
4
|
+
# TODO: Refactor this class to delegate the responsability of complex fields
|
5
|
+
# to a specific Loader (like include for IncludeConfigLoader),
|
6
|
+
# maybe renaming to RootConfigLoader
|
7
7
|
|
8
8
|
# rubocop:disable Metrics/ClassLength
|
9
9
|
class ConfigLoader
|
10
10
|
using Djin::HashExtensions
|
11
11
|
RESERVED_WORDS = %w[djin_version variables tasks include].freeze
|
12
12
|
|
13
|
-
|
14
|
-
FileNotFoundError = Class.new(Interpreter::InvalidConfigurationError)
|
15
|
-
|
16
|
-
def self.load_files!(*files, runtime_config: {}, base_directory: '.')
|
13
|
+
def self.load_files!(*files, context_config: {}, base_directory: '.')
|
17
14
|
files.map do |file_path|
|
18
|
-
ConfigLoader.load!(file_path,
|
15
|
+
ConfigLoader.load!(file_path, context_config: context_config, base_directory: base_directory)
|
19
16
|
end&.reduce(:deep_merge)
|
20
17
|
end
|
21
18
|
|
22
|
-
def self.load!(template_file_path,
|
23
|
-
new(template_file_path,
|
19
|
+
def self.load!(template_file_path, context_config: {}, base_directory: '.')
|
20
|
+
new(template_file_path, context_config: context_config, base_directory: base_directory).load!
|
24
21
|
end
|
25
22
|
|
26
|
-
def initialize(template_file_path,
|
23
|
+
def initialize(template_file_path, context_config: {}, base_directory: '.')
|
27
24
|
@base_directory = Pathname.new(base_directory)
|
28
25
|
@template_file = @base_directory.join(template_file_path)
|
29
26
|
|
30
27
|
file_not_found!(@template_file) unless @template_file.exist?
|
31
28
|
|
32
29
|
@template_file_content = Djin.cache.fetch(@template_file.realpath.to_s) { @template_file.read }
|
33
|
-
@
|
30
|
+
@context_config = context_config
|
34
31
|
end
|
35
32
|
|
36
33
|
def load!
|
@@ -107,7 +104,7 @@ module Djin
|
|
107
104
|
present_include_configs&.map do |present_include|
|
108
105
|
ConfigLoader.load!(present_include.file, base_directory: @template_file.dirname,
|
109
106
|
# TODO: Rename to context_config
|
110
|
-
|
107
|
+
context_config: present_include.context)
|
111
108
|
end&.reduce(:deep_merge)
|
112
109
|
end
|
113
110
|
end
|
@@ -120,18 +117,9 @@ module Djin
|
|
120
117
|
include_configs&.select(&:missing?)
|
121
118
|
end
|
122
119
|
|
123
|
-
# TODO: Refactor to move include methods to a specific IncludeConfigLoader, maybe rename IncludeResolver
|
124
120
|
def include_configs
|
125
|
-
@include_configs ||=
|
126
|
-
|
127
|
-
resolver = IncludeResolver.new(base_directory: @template_file.dirname)
|
128
|
-
|
129
|
-
include_djin_config = raw_djin_config['include'] || []
|
130
|
-
|
131
|
-
include_djin_config.map do |include_config|
|
132
|
-
resolver.call(include_config)
|
133
|
-
end
|
134
|
-
end
|
121
|
+
@include_configs ||= Djin::IncludeConfigLoader.load!(raw_djin_config['include'],
|
122
|
+
base_directory: @template_file.dirname)
|
135
123
|
end
|
136
124
|
|
137
125
|
def args
|
@@ -147,9 +135,9 @@ module Djin
|
|
147
135
|
end
|
148
136
|
|
149
137
|
def raw_djin_config
|
150
|
-
@raw_djin_config ||= yaml_load(@template_file_content).deep_merge(@
|
138
|
+
@raw_djin_config ||= yaml_load(@template_file_content).deep_merge(@context_config)
|
151
139
|
rescue Psych::SyntaxError => e
|
152
|
-
raise
|
140
|
+
raise InvalidConfigFileError, "File: #{@template_file.realpath}\n #{e.message}"
|
153
141
|
end
|
154
142
|
|
155
143
|
def rendered_djin_config
|
@@ -160,7 +148,7 @@ module Djin
|
|
160
148
|
args: args.join(' '),
|
161
149
|
args?: args.any?,
|
162
150
|
**locals)
|
163
|
-
yaml_load(rendered_yaml).merge(@
|
151
|
+
yaml_load(rendered_yaml).merge(@context_config)
|
164
152
|
end
|
165
153
|
end
|
166
154
|
|
@@ -169,11 +157,11 @@ module Djin
|
|
169
157
|
end
|
170
158
|
|
171
159
|
def validate_version!
|
172
|
-
raise
|
160
|
+
raise MissingVersionError, 'Missing djin_version' unless version
|
173
161
|
|
174
162
|
return if file_config.version_supported?
|
175
163
|
|
176
|
-
raise
|
164
|
+
raise VersionNotSupportedError, "Version #{version} is not supported, use #{Djin::VERSION} or higher"
|
177
165
|
end
|
178
166
|
|
179
167
|
def validate_missing_config!
|
data/lib/djin/errors.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Djin
|
4
|
+
InvalidConfigurationError = Class.new(StandardError)
|
5
|
+
InvalidConfigFileError = Class.new(InvalidConfigurationError)
|
6
|
+
MissingVersionError = Class.new(InvalidConfigurationError)
|
7
|
+
VersionNotSupportedError = Class.new(InvalidConfigurationError)
|
8
|
+
InvalidSyntaxError = Class.new(InvalidConfigurationError)
|
9
|
+
FileNotFoundError = Class.new(InvalidConfigurationError)
|
10
|
+
end
|
@@ -1,10 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Djin
|
4
|
-
class
|
4
|
+
class IncludeConfigLoader
|
5
5
|
using ObjectExtensions
|
6
6
|
using HashExtensions
|
7
7
|
|
8
|
+
def self.load!(include_djin_config, **options)
|
9
|
+
new(**options).load!(include_djin_config)
|
10
|
+
end
|
11
|
+
|
8
12
|
def initialize(base_directory: '.', remote_directory: '~/.djin/remote', entity_class: Djin::IncludeConfig)
|
9
13
|
# TODO: Use chain of responsability
|
10
14
|
@base_directory = Pathname.new(base_directory)
|
@@ -12,15 +16,33 @@ module Djin
|
|
12
16
|
@entity_class = entity_class
|
13
17
|
end
|
14
18
|
|
15
|
-
def
|
19
|
+
def load!(include_djin_config)
|
20
|
+
load_configs(include_djin_config)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def load_configs(include_djin_config)
|
26
|
+
include_djin_config ||= []
|
27
|
+
|
28
|
+
include_contract = IncludeContract.new
|
29
|
+
|
30
|
+
include_djin_config.map do |include_params|
|
31
|
+
result = include_contract.call(include_params)
|
32
|
+
|
33
|
+
raise InvalidSyntaxError, { include: result.errors.to_h } if result.failure?
|
34
|
+
|
35
|
+
resolve_include(include_params)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def resolve_include(params)
|
16
40
|
include_config_params = remote_handler(params)
|
17
41
|
include_config_params ||= local_handler(params)
|
18
42
|
|
19
43
|
build_entity(include_config_params)
|
20
44
|
end
|
21
45
|
|
22
|
-
private
|
23
|
-
|
24
46
|
def remote_handler(params)
|
25
47
|
return if params['git'].blank?
|
26
48
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Djin
|
4
|
+
class IncludeContract < Dry::Validation::Contract
|
5
|
+
using Djin::ObjectExtensions
|
6
|
+
|
7
|
+
GIT_URI_REGEXP = Regexp.new('(\w+://)(.+@)*([\w\d\.]+)(:[\d]+){0,1}/*(.*)')
|
8
|
+
|
9
|
+
ContextSchema = Dry::Schema.Params do
|
10
|
+
optional(:variables).filled(:hash)
|
11
|
+
# TODO: Add the rest
|
12
|
+
end
|
13
|
+
|
14
|
+
params do
|
15
|
+
optional(:context).filled do
|
16
|
+
hash(ContextSchema)
|
17
|
+
end
|
18
|
+
required(:file).filled(:string)
|
19
|
+
optional(:git).filled(:string)
|
20
|
+
optional(:version).filled(:string)
|
21
|
+
end
|
22
|
+
|
23
|
+
rule(:git) do
|
24
|
+
key.failure("Invalid git uri in: #{value}") if value.present? && !GIT_URI_REGEXP.match?(value)
|
25
|
+
end
|
26
|
+
|
27
|
+
# TODO: Add more validations to file and to restricted unespected keys
|
28
|
+
end
|
29
|
+
end
|
data/lib/djin/interpreter.rb
CHANGED
@@ -1,16 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Djin
|
4
|
+
# TODO: Refactor to TaskConfigLoader and make COnfigLoader to use this class
|
4
5
|
class Interpreter
|
5
6
|
using Djin::HashExtensions
|
6
7
|
|
7
|
-
# TODO: Move Errors to ConfigLoader
|
8
|
-
InvalidConfigurationError = Class.new(StandardError)
|
9
|
-
InvalidConfigFileError = Class.new(InvalidConfigurationError)
|
10
|
-
MissingVersionError = Class.new(InvalidConfigurationError)
|
11
|
-
VersionNotSupportedError = Class.new(InvalidConfigurationError)
|
12
|
-
InvalidSyntaxError = Class.new(InvalidConfigurationError)
|
13
|
-
|
14
8
|
class << self
|
15
9
|
# rubocop:disable Metrics/AbcSize
|
16
10
|
def load!(file_config)
|
data/lib/djin/version.rb
CHANGED
data/wait-for-it.sh
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
# Use this script to test if a given TCP host/port are available
|
3
|
+
# Credits: https://github.com/vishnubob/wait-for-it
|
4
|
+
|
5
|
+
WAITFORIT_cmdname=${0##*/}
|
6
|
+
|
7
|
+
echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
|
8
|
+
|
9
|
+
usage()
|
10
|
+
{
|
11
|
+
cat << USAGE >&2
|
12
|
+
Usage:
|
13
|
+
$WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args]
|
14
|
+
-h HOST | --host=HOST Host or IP under test
|
15
|
+
-p PORT | --port=PORT TCP port under test
|
16
|
+
Alternatively, you specify the host and port as host:port
|
17
|
+
-s | --strict Only execute subcommand if the test succeeds
|
18
|
+
-q | --quiet Don't output any status messages
|
19
|
+
-t TIMEOUT | --timeout=TIMEOUT
|
20
|
+
Timeout in seconds, zero for no timeout
|
21
|
+
-- COMMAND ARGS Execute command with args after the test finishes
|
22
|
+
USAGE
|
23
|
+
exit 1
|
24
|
+
}
|
25
|
+
|
26
|
+
wait_for()
|
27
|
+
{
|
28
|
+
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
|
29
|
+
echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
|
30
|
+
else
|
31
|
+
echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout"
|
32
|
+
fi
|
33
|
+
WAITFORIT_start_ts=$(date +%s)
|
34
|
+
while :
|
35
|
+
do
|
36
|
+
if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then
|
37
|
+
nc -z $WAITFORIT_HOST $WAITFORIT_PORT
|
38
|
+
WAITFORIT_result=$?
|
39
|
+
else
|
40
|
+
(echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1
|
41
|
+
WAITFORIT_result=$?
|
42
|
+
fi
|
43
|
+
if [[ $WAITFORIT_result -eq 0 ]]; then
|
44
|
+
WAITFORIT_end_ts=$(date +%s)
|
45
|
+
echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"
|
46
|
+
break
|
47
|
+
fi
|
48
|
+
sleep 1
|
49
|
+
done
|
50
|
+
return $WAITFORIT_result
|
51
|
+
}
|
52
|
+
|
53
|
+
wait_for_wrapper()
|
54
|
+
{
|
55
|
+
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
|
56
|
+
if [[ $WAITFORIT_QUIET -eq 1 ]]; then
|
57
|
+
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
|
58
|
+
else
|
59
|
+
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
|
60
|
+
fi
|
61
|
+
WAITFORIT_PID=$!
|
62
|
+
trap "kill -INT -$WAITFORIT_PID" INT
|
63
|
+
wait $WAITFORIT_PID
|
64
|
+
WAITFORIT_RESULT=$?
|
65
|
+
if [[ $WAITFORIT_RESULT -ne 0 ]]; then
|
66
|
+
echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
|
67
|
+
fi
|
68
|
+
return $WAITFORIT_RESULT
|
69
|
+
}
|
70
|
+
|
71
|
+
# process arguments
|
72
|
+
while [[ $# -gt 0 ]]
|
73
|
+
do
|
74
|
+
case "$1" in
|
75
|
+
*:* )
|
76
|
+
WAITFORIT_hostport=(${1//:/ })
|
77
|
+
WAITFORIT_HOST=${WAITFORIT_hostport[0]}
|
78
|
+
WAITFORIT_PORT=${WAITFORIT_hostport[1]}
|
79
|
+
shift 1
|
80
|
+
;;
|
81
|
+
--child)
|
82
|
+
WAITFORIT_CHILD=1
|
83
|
+
shift 1
|
84
|
+
;;
|
85
|
+
-q | --quiet)
|
86
|
+
WAITFORIT_QUIET=1
|
87
|
+
shift 1
|
88
|
+
;;
|
89
|
+
-s | --strict)
|
90
|
+
WAITFORIT_STRICT=1
|
91
|
+
shift 1
|
92
|
+
;;
|
93
|
+
-h)
|
94
|
+
WAITFORIT_HOST="$2"
|
95
|
+
if [[ $WAITFORIT_HOST == "" ]]; then break; fi
|
96
|
+
shift 2
|
97
|
+
;;
|
98
|
+
--host=*)
|
99
|
+
WAITFORIT_HOST="${1#*=}"
|
100
|
+
shift 1
|
101
|
+
;;
|
102
|
+
-p)
|
103
|
+
WAITFORIT_PORT="$2"
|
104
|
+
if [[ $WAITFORIT_PORT == "" ]]; then break; fi
|
105
|
+
shift 2
|
106
|
+
;;
|
107
|
+
--port=*)
|
108
|
+
WAITFORIT_PORT="${1#*=}"
|
109
|
+
shift 1
|
110
|
+
;;
|
111
|
+
-t)
|
112
|
+
WAITFORIT_TIMEOUT="$2"
|
113
|
+
if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi
|
114
|
+
shift 2
|
115
|
+
;;
|
116
|
+
--timeout=*)
|
117
|
+
WAITFORIT_TIMEOUT="${1#*=}"
|
118
|
+
shift 1
|
119
|
+
;;
|
120
|
+
--)
|
121
|
+
shift
|
122
|
+
WAITFORIT_CLI=("$@")
|
123
|
+
break
|
124
|
+
;;
|
125
|
+
--help)
|
126
|
+
usage
|
127
|
+
;;
|
128
|
+
*)
|
129
|
+
echoerr "Unknown argument: $1"
|
130
|
+
usage
|
131
|
+
;;
|
132
|
+
esac
|
133
|
+
done
|
134
|
+
|
135
|
+
if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then
|
136
|
+
echoerr "Error: you need to provide a host and port to test."
|
137
|
+
usage
|
138
|
+
fi
|
139
|
+
|
140
|
+
WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15}
|
141
|
+
WAITFORIT_STRICT=${WAITFORIT_STRICT:-0}
|
142
|
+
WAITFORIT_CHILD=${WAITFORIT_CHILD:-0}
|
143
|
+
WAITFORIT_QUIET=${WAITFORIT_QUIET:-0}
|
144
|
+
|
145
|
+
# Check to see if timeout is from busybox?
|
146
|
+
WAITFORIT_TIMEOUT_PATH=$(type -p timeout)
|
147
|
+
WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH)
|
148
|
+
|
149
|
+
WAITFORIT_BUSYTIMEFLAG=""
|
150
|
+
if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then
|
151
|
+
WAITFORIT_ISBUSY=1
|
152
|
+
# Check if busybox timeout uses -t flag
|
153
|
+
# (recent Alpine versions don't support -t anymore)
|
154
|
+
if timeout &>/dev/stdout | grep -q -e '-t '; then
|
155
|
+
WAITFORIT_BUSYTIMEFLAG="-t"
|
156
|
+
fi
|
157
|
+
else
|
158
|
+
WAITFORIT_ISBUSY=0
|
159
|
+
fi
|
160
|
+
|
161
|
+
if [[ $WAITFORIT_CHILD -gt 0 ]]; then
|
162
|
+
wait_for
|
163
|
+
WAITFORIT_RESULT=$?
|
164
|
+
exit $WAITFORIT_RESULT
|
165
|
+
else
|
166
|
+
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
|
167
|
+
wait_for_wrapper
|
168
|
+
WAITFORIT_RESULT=$?
|
169
|
+
else
|
170
|
+
wait_for
|
171
|
+
WAITFORIT_RESULT=$?
|
172
|
+
fi
|
173
|
+
fi
|
174
|
+
|
175
|
+
if [[ $WAITFORIT_CLI != "" ]]; then
|
176
|
+
if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then
|
177
|
+
echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess"
|
178
|
+
exit $WAITFORIT_RESULT
|
179
|
+
fi
|
180
|
+
exec "${WAITFORIT_CLI[@]}"
|
181
|
+
else
|
182
|
+
exit $WAITFORIT_RESULT
|
183
|
+
fi
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: djin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carlos Atkinson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-cli
|
@@ -236,10 +236,12 @@ files:
|
|
236
236
|
- lib/djin/entities/main_config.rb
|
237
237
|
- lib/djin/entities/task.rb
|
238
238
|
- lib/djin/entities/types.rb
|
239
|
+
- lib/djin/errors.rb
|
239
240
|
- lib/djin/executor.rb
|
240
241
|
- lib/djin/extensions/hash_extensions.rb
|
241
242
|
- lib/djin/extensions/object_extensions.rb
|
242
|
-
- lib/djin/
|
243
|
+
- lib/djin/include_config_loader.rb
|
244
|
+
- lib/djin/include_contract.rb
|
243
245
|
- lib/djin/interpreter.rb
|
244
246
|
- lib/djin/interpreter/base_command_builder.rb
|
245
247
|
- lib/djin/interpreter/docker_command_builder.rb
|
@@ -251,6 +253,7 @@ files:
|
|
251
253
|
- lib/djin/root_cli_parser.rb
|
252
254
|
- lib/djin/task_contract.rb
|
253
255
|
- lib/djin/version.rb
|
256
|
+
- wait-for-it.sh
|
254
257
|
homepage: https://github.com/catks/djin
|
255
258
|
licenses:
|
256
259
|
- MIT
|