rudder 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.rubocop.yml +16 -0
- data/.travis.yml +5 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +53 -0
- data/LICENSE +21 -0
- data/README.md +101 -0
- data/Rakefile +24 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/docker-compose.yml +26 -0
- data/docs/Rudder.html +382 -0
- data/docs/Rudder/DSL.html +456 -0
- data/docs/Rudder/DSL/Component.html +645 -0
- data/docs/Rudder/DSL/Group.html +733 -0
- data/docs/Rudder/DSL/Job.html +487 -0
- data/docs/Rudder/DSL/Pipeline.html +1869 -0
- data/docs/Rudder/DSL/Resource.html +584 -0
- data/docs/Rudder/DSL/ResourceType.html +223 -0
- data/docs/Rudder/DSL/Util.html +324 -0
- data/docs/_index.html +211 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +496 -0
- data/docs/file.README.html +191 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +191 -0
- data/docs/js/app.js +303 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +347 -0
- data/docs/top-level-namespace.html +110 -0
- data/examples/README.md +6 -0
- data/examples/groups/README.md +12 -0
- data/examples/groups/groups_pipeline.rb +34 -0
- data/examples/groups/jobs/bash_stuff/date.rb +16 -0
- data/examples/groups/jobs/bash_stuff/hello.rb +17 -0
- data/examples/groups/jobs/git_stuff/log.rb +22 -0
- data/examples/groups/jobs/git_stuff/ls.rb +21 -0
- data/examples/groups/resources/rudder_git.rb +6 -0
- data/examples/groups/resources/timer.rb +5 -0
- data/examples/hello_world_pipeline.rb +44 -0
- data/examples/images/groups/groups_all.png +0 -0
- data/examples/images/groups/groups_bash_stuff.png +0 -0
- data/examples/images/groups/groups_git_stuff.png +0 -0
- data/examples/images/hello_world.png +0 -0
- data/examples/images/includes/includes.png +0 -0
- data/examples/images/shared/borrows.png +0 -0
- data/examples/images/shared/common.png +0 -0
- data/examples/images/shared/wrapper.png +0 -0
- data/examples/includes/README.md +7 -0
- data/examples/includes/includes_pipeline.rb +6 -0
- data/examples/includes/jobs/log.rb +15 -0
- data/examples/includes/resources/rudder_git.rb +5 -0
- data/examples/shared/README.md +21 -0
- data/examples/shared/borrows_pipeline.rb +31 -0
- data/examples/shared/common_pipeline.rb +34 -0
- data/examples/shared/wrapper_pipeline.rb +51 -0
- data/exe/rudder +52 -0
- data/lib/rudder.rb +35 -0
- data/lib/rudder/dsl.rb +54 -0
- data/lib/rudder/dsl/component.rb +79 -0
- data/lib/rudder/dsl/group.rb +110 -0
- data/lib/rudder/dsl/job.rb +65 -0
- data/lib/rudder/dsl/pipeline.rb +374 -0
- data/lib/rudder/dsl/resource.rb +82 -0
- data/lib/rudder/dsl/resource_type.rb +45 -0
- data/lib/rudder/dsl/util.rb +48 -0
- data/lib/rudder/version.rb +5 -0
- data/lib/tasks/docker.rb +11 -0
- data/rudder.gemspec +29 -0
- metadata +189 -0
data/examples/README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Groups Example
|
|
2
|
+
|
|
3
|
+
The [`groups_pipeline.rb`](./groups_pipeline.rb) shows how concourse groups can be utilized
|
|
4
|
+
within `rudder`. This pipeline also shows how to indiscriminately import
|
|
5
|
+
pipelines from other directories.
|
|
6
|
+
|
|
7
|
+
- The All group:
|
|
8
|
+

|
|
9
|
+
- The Bash Stuff group:
|
|
10
|
+

|
|
11
|
+
- The Git Stuff group:
|
|
12
|
+

|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
@parent_dir = File.dirname(__FILE__)
|
|
4
|
+
def relative_files(path)
|
|
5
|
+
Dir[File.join(@parent_dir, path)]
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Load all the resources
|
|
9
|
+
relative_files('resources/*').each do |path|
|
|
10
|
+
# Pipline#load includes always loads files relative to where itself, so
|
|
11
|
+
# we need to remove the parent directory from this path
|
|
12
|
+
res = load path.sub(@parent_dir, '')
|
|
13
|
+
resources.merge! res.resources
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Load all the jobs and stick them in groups by directory
|
|
17
|
+
relative_files('jobs/*').each do |group_dir|
|
|
18
|
+
group_name = File.basename group_dir
|
|
19
|
+
group group_name do |pipeline|
|
|
20
|
+
Dir[File.join(group_dir, '*')].each do |job_path|
|
|
21
|
+
parent_dir = File.dirname __FILE__
|
|
22
|
+
job_pipe = pipeline.load(job_path.sub(parent_dir, ''), resources: pipeline.resources)
|
|
23
|
+
pipeline.jobs.merge! job_pipe.jobs
|
|
24
|
+
job_pipe.jobs.keys.each { |job_name| job job_name }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Add all of the jobs to a super group
|
|
30
|
+
group :all do |pipeline|
|
|
31
|
+
pipeline.jobs.keys.each do |job_name|
|
|
32
|
+
jobs << job_name
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
time_resources = @resources.values.select { |r| r.type == :time }
|
|
4
|
+
|
|
5
|
+
time_resources.each do |r|
|
|
6
|
+
job :date do
|
|
7
|
+
plan << { get: r.name, trigger: true }
|
|
8
|
+
plan << { task: 'print_date', config: {
|
|
9
|
+
platform: 'linux',
|
|
10
|
+
image_resource: { type: 'docker-image', source: { repository: 'busybox' } },
|
|
11
|
+
run: {
|
|
12
|
+
path: 'date'
|
|
13
|
+
}
|
|
14
|
+
} }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
time_resources = resources.values.select { |r| r.type == :time }
|
|
4
|
+
|
|
5
|
+
time_resources.each do |r|
|
|
6
|
+
job :hello do
|
|
7
|
+
plan << { get: r.name, trigger: true }
|
|
8
|
+
plan << { task: 'print_hello', config: {
|
|
9
|
+
platform: 'linux',
|
|
10
|
+
image_resource: { type: 'docker-image', source: { repository: 'busybox' } },
|
|
11
|
+
run: {
|
|
12
|
+
path: 'echo',
|
|
13
|
+
args: ['Hello']
|
|
14
|
+
}
|
|
15
|
+
} }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
git_resources = resources.values.select { |r| r.type == :git }
|
|
4
|
+
|
|
5
|
+
git_resources.each do |r|
|
|
6
|
+
job "git log #{r.name}" do
|
|
7
|
+
plan << { get: r.name, trigger: true }
|
|
8
|
+
task = {
|
|
9
|
+
task: "git log #{r.name}", config: {
|
|
10
|
+
inputs: [name: r.name],
|
|
11
|
+
platform: 'linux',
|
|
12
|
+
image_resource: { type: 'docker-image', source: { repository: 'alpine/git' } },
|
|
13
|
+
run: {
|
|
14
|
+
path: 'git',
|
|
15
|
+
args: ['--git-dir', File.join(r.name.to_s, '.git'),
|
|
16
|
+
'--no-pager', 'log']
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
plan << task
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
git_resources = resources.values.select { |r| r.type == :git }
|
|
4
|
+
|
|
5
|
+
git_resources.each do |r|
|
|
6
|
+
job "ls #{r.name}" do
|
|
7
|
+
plan << { get: r.name, trigger: true }
|
|
8
|
+
task = {
|
|
9
|
+
task: "ls #{r.name}", config: {
|
|
10
|
+
inputs: [name: r.name],
|
|
11
|
+
platform: 'linux',
|
|
12
|
+
image_resource: { type: 'docker-image', source: { repository: 'alpine/git' } },
|
|
13
|
+
run: {
|
|
14
|
+
path: 'ls',
|
|
15
|
+
args: [r.name]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
plan << task
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
resource :rudder_git, :git do
|
|
4
|
+
# The source field dictionary is available to be directly interacted with
|
|
5
|
+
source[:uri] = 'https://github.com/jhmcstanton/rudder.git'
|
|
6
|
+
source[:branch] = 'master'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
resource :timer, :time do
|
|
10
|
+
# The source field can also be assigned via a method
|
|
11
|
+
source(interval: '5m')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
job :getter do
|
|
15
|
+
plan [in_parallel: [{ get: :rudder_git }, { get: :timer, trigger: true }]]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
job :hello_world do
|
|
19
|
+
# Plan array can be hooked into directly
|
|
20
|
+
plan << { get: :timer, trigger: true, passed: [:getter] }
|
|
21
|
+
plan << { task: 'print_hello', config: {
|
|
22
|
+
platform: 'linux',
|
|
23
|
+
image_resource: { type: 'docker-image', source: { repository: 'busybox' } },
|
|
24
|
+
run: {
|
|
25
|
+
path: 'echo',
|
|
26
|
+
args: ['Hello', 'World!']
|
|
27
|
+
}
|
|
28
|
+
} }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# pipeline here allows access to previously defined pipeline components
|
|
32
|
+
job :cat_self do |pipeline|
|
|
33
|
+
# The plan can also be appended to as a method
|
|
34
|
+
plan({ get: :rudder_git, trigger: true, passed: [:getter] },
|
|
35
|
+
task: 'cat this pipeline', config: {
|
|
36
|
+
inputs: [name: :rudder_git],
|
|
37
|
+
platform: 'linux',
|
|
38
|
+
image_resource: { type: 'docker-image', source: { repository: 'busybox' } },
|
|
39
|
+
run: {
|
|
40
|
+
path: 'cat',
|
|
41
|
+
args: [pipeline.rudder_git.sub_path('examples/hello_world.rb')]
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
end
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Includes Example
|
|
2
|
+
|
|
3
|
+
The [`includes_pipeline.rb`](./includes_pipeline.rb) pipeline shows how to load pipeline components
|
|
4
|
+
(jobs, resources, resource_types, groups) from files and include them
|
|
5
|
+
into your pipelines.
|
|
6
|
+
|
|
7
|
+

|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
task = {
|
|
4
|
+
task: 'git log', config: {
|
|
5
|
+
# input still needed
|
|
6
|
+
platform: 'linux',
|
|
7
|
+
image_resource: { type: 'docker-image', source: { repository: 'alpine/git' } },
|
|
8
|
+
run: {
|
|
9
|
+
path: 'find',
|
|
10
|
+
args: ['.', '-iname', '*.git', '-exec',
|
|
11
|
+
'git', '--git-dir', '{}', '--no-pager', 'log', ';']
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
plan << task
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Shared Example
|
|
2
|
+
|
|
3
|
+
This example is a bit contrived, but serves to illustrate how joining pipelines works.
|
|
4
|
+
|
|
5
|
+
[`common_pipeline.rb`](./common_pipeline.rb) is a full, standalone pipeline with resources
|
|
6
|
+
and several jobs that is fully flyable.
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
[`wrapper_pipeline.rb`](./wrapper_pipeline.rb) is another full pipeline that incorporates
|
|
11
|
+
the entirety of `common_pipeline.rb` and augments it with an additional timer, one new
|
|
12
|
+
job that requires the final job from `common_pipeline.rb`, and its own job that only
|
|
13
|
+
depends on a single resource from the common pipeline.
|
|
14
|
+
|
|
15
|
+

|
|
16
|
+
|
|
17
|
+
[`borrows_pipeline.rb`](./borrows_pipeline.rb) is a single job pipeline that borrows
|
|
18
|
+
the git resource from the `common_pipeline.rb` (actually, it would borrow any git
|
|
19
|
+
resource from that pipeline, there just happens to be only one right now).
|
|
20
|
+
|
|
21
|
+

|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
common = load 'common_pipeline.rb'
|
|
4
|
+
|
|
5
|
+
resource :timer, :time do
|
|
6
|
+
source[:interval] = '30m'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Borrow any git resources defined in common
|
|
10
|
+
git_resources = common.resources.select { |_name, r| r.type == :git }
|
|
11
|
+
resources.merge! git_resources
|
|
12
|
+
|
|
13
|
+
job 'Just borrowing the git resource' do
|
|
14
|
+
git_names = git_resources.keys
|
|
15
|
+
gets = git_names.map { |name| { get: name } }
|
|
16
|
+
gets << { get: :timer, trigger: true }
|
|
17
|
+
plan [in_parallel: gets]
|
|
18
|
+
|
|
19
|
+
task = {
|
|
20
|
+
task: 'ls all the gits', config: {
|
|
21
|
+
platform: 'linux',
|
|
22
|
+
inputs: [name: :rudder_git],
|
|
23
|
+
image_resource: { type: 'docker-image', source: { repository: 'busybox' } },
|
|
24
|
+
run: {
|
|
25
|
+
path: 'ls',
|
|
26
|
+
args: git_names
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
plan << task
|
|
31
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
resource :rudder_git, :git do
|
|
4
|
+
source[:uri] = 'https://github.com/jhmcstanton/rudder.git'
|
|
5
|
+
source[:branch] = 'master'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
get_rudder = { get: :rudder_git, trigger: true }
|
|
9
|
+
|
|
10
|
+
print_hello = {
|
|
11
|
+
task: 'print_hello', config: {
|
|
12
|
+
platform: 'linux',
|
|
13
|
+
image_resource: { type: 'docker-image', source: { repository: 'busybox' } },
|
|
14
|
+
run: {
|
|
15
|
+
path: 'echo',
|
|
16
|
+
args: ['Hello', 'World!']
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
def mk_name(job_index)
|
|
22
|
+
"Yo #{job_index}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
num_jobs = 3
|
|
26
|
+
(1..num_jobs).each do |i|
|
|
27
|
+
name = mk_name i
|
|
28
|
+
job name do |p|
|
|
29
|
+
get = get_rudder.dup
|
|
30
|
+
get[:passed] = [p.mk_name(i - 1)] if i > 1
|
|
31
|
+
plan << get
|
|
32
|
+
plan << print_hello
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
common = load('common_pipeline.rb')
|
|
4
|
+
|
|
5
|
+
resource :timer, :time do
|
|
6
|
+
source[:interval] = '5m'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Add a timer to the first job
|
|
10
|
+
get_timer_task = { get: :timer, trigger: true }
|
|
11
|
+
start_plan = common.jobs.values.first.plan
|
|
12
|
+
start_plan << get_timer_task
|
|
13
|
+
|
|
14
|
+
resources.merge! common.resources
|
|
15
|
+
jobs .merge! common.jobs
|
|
16
|
+
|
|
17
|
+
job 'An extra job that the wrapper pipeline requires' do
|
|
18
|
+
plan << get_timer_task
|
|
19
|
+
date = {
|
|
20
|
+
task: 'print the date', config: {
|
|
21
|
+
platform: 'linux',
|
|
22
|
+
image_resource: { type: 'docker-image', source: { repository: 'busybox' } },
|
|
23
|
+
run: {
|
|
24
|
+
path: 'date'
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
plan << date
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
job 'Goodbye from the Wrapper Pipeline' do |_pipeline|
|
|
32
|
+
# Get the last job defined in the previous pipeline
|
|
33
|
+
# so that we can depend on it in this job
|
|
34
|
+
last_job = common.jobs.values.last
|
|
35
|
+
last_job.plan.select { |task| task.key? :get }.each do |task|
|
|
36
|
+
task = task.dup
|
|
37
|
+
task[:passed] = [last_job.name]
|
|
38
|
+
plan << task
|
|
39
|
+
end
|
|
40
|
+
task = {
|
|
41
|
+
task: 'print_outer', config: {
|
|
42
|
+
platform: 'linux',
|
|
43
|
+
image_resource: { type: 'docker-image', source: { repository: 'busybox' } },
|
|
44
|
+
run: {
|
|
45
|
+
path: 'echo',
|
|
46
|
+
args: ['This is the outer pipeline. Good bye!']
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
plan << task
|
|
51
|
+
end
|
data/exe/rudder
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'optparse'
|
|
5
|
+
require 'yaml'
|
|
6
|
+
|
|
7
|
+
require 'rudder'
|
|
8
|
+
|
|
9
|
+
name = File.basename __FILE__
|
|
10
|
+
|
|
11
|
+
# TODO: Figure out a nice way to join these options with fly's without
|
|
12
|
+
# tieing them together
|
|
13
|
+
options = {}
|
|
14
|
+
optparse = OptionParser.new do |opts|
|
|
15
|
+
opts.banner = "Usage: #{name} [options]"
|
|
16
|
+
|
|
17
|
+
opts.on('-o', '--output YAML_PATH', 'YAML_PATH to write the pipeline config') do |p|
|
|
18
|
+
options[:output] = p
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
opts.on('-c', '--config RUDDER_CONFIG', 'Path to the RUDDER_CONFIG file to evaluate') do |c|
|
|
22
|
+
options[:rudder] = c
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
opts.on('-v', '--version', 'Show version') do
|
|
26
|
+
options[:version] = true
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
optparse.parse!
|
|
30
|
+
|
|
31
|
+
if options[:version]
|
|
32
|
+
puts "Rudder Version: #{Rudder::VERSION}"
|
|
33
|
+
exit
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
unless options[:rudder]
|
|
37
|
+
puts 'Must provide RUDDER_CONFIG as option'
|
|
38
|
+
puts optparse.help
|
|
39
|
+
exit 1
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
pipeline = Rudder.compile(options[:rudder])
|
|
43
|
+
|
|
44
|
+
output = STDOUT
|
|
45
|
+
if options[:output]
|
|
46
|
+
output = File.open(options[:output], 'w+')
|
|
47
|
+
at_exit do
|
|
48
|
+
output.close
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
Rudder.dump(pipeline, output)
|