pipely 0.3.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41fc3328b9562c634d8431f24de10627f682e827
4
- data.tar.gz: 7bdc7a4693e34194baa787be589e1ca4e28d561d
3
+ metadata.gz: 9b9b109c0262cd83b9db819b8464e1ed39a6bef6
4
+ data.tar.gz: 633b3e1c8bb00323199629919714dec0cce1523f
5
5
  SHA512:
6
- metadata.gz: c6bb2fb0e3872e128241b0760ef95ddc97a5c7baf534439eae8dcfaa76d7d115196bb1254e98723125dbadf5c5aba485c7d65ce183bb1e593149d2a2a23c7bca
7
- data.tar.gz: 13495dbb6503f46cac2cd52682f9b3245e38970641e69081d59e13922f37987d3ac169253cf9fc68601564883bbee68523cfb0d4677386ef15720f88e7c8feb0
6
+ metadata.gz: 9576d0aeb1273ebf96021d60cd1f6fb98f9f800cdae3bcd14a1ea6ca5919864ba3896ff99668c340ef0f25b15fe1280997ca7f997ccabe78ddbb4709762c216a
7
+ data.tar.gz: ef09a07d9ecdb00ea13633455b88f262336756e3e8d51889dd989be384b0ce01192ccbc7c9d474b21d436a2a055c67c1d134bf9ed83786af47add4571b5a2a12
data/bin/pipely CHANGED
@@ -1,40 +1,16 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'pipely'
4
- require 'optparse'
5
4
 
6
- pipeline_id = input_path = output_path = nil
7
- verbose = automatic_open = false
5
+ options = Pipely::Options.parse
8
6
 
9
- OptionParser.new do |opts|
10
- opts.banner = "Usage: pipely [options]"
7
+ if options.pipeline_id
8
+ Pipely::Actions::GraphLivePipeline.new(options).execute
11
9
 
12
- opts.on("-p", "--pipeline-id PIPELINE_ID",
13
- "ID of a live pipeline to visualize with live execution statuses") do |id|
14
- pipeline_id = id
15
- end
10
+ elsif options.input_path
11
+ Pipely::Actions::GraphFilePipeline.new(options).execute
16
12
 
17
- opts.on("-i", "--input PATH",
18
- "Path to a JSON pipeline definition file to visualize") do |input|
19
- input_path = input
20
- end
13
+ else
14
+ Pipely::Actions::ListLivePipelines.new(options).execute
21
15
 
22
- opts.on("-o", "--output PATH",
23
- "Path to write PNG file(s) of graph visualization(s)") do |output|
24
- output_path = output
25
- end
26
- end.parse!
27
-
28
- if pipeline_id
29
- live_pipeline = Pipely::LivePipeline.new(pipeline_id)
30
- live_pipeline.print_runs_report
31
- live_pipeline.render_graphs
32
-
33
- elsif input_path
34
- definition_json = File.open(input_path).read
35
- output_base = File.basename(input_path,".*") + '.png'
36
- output_file = output_path ? File.join(output_path, output_base) : output_base
37
-
38
- puts "Generating #{output_file}"
39
- Pipely.draw(definition_json, output_file)
40
16
  end
data/lib/pipely.rb CHANGED
@@ -1,6 +1,9 @@
1
+ require 'pipely/options'
2
+ require 'pipely/actions'
1
3
  require 'pipely/definition'
2
4
  require 'pipely/graph_builder'
3
5
  require 'pipely/live_pipeline'
6
+ require 'pipely/s3_writer'
4
7
 
5
8
  # The top-level module for this gem. It provides the recommended public
6
9
  # interface for using Pipely to visualize and manipulate your Data Pipeline
@@ -18,7 +21,14 @@ module Pipely
18
21
  graph_builder = GraphBuilder.new
19
22
 
20
23
  graph = graph_builder.build(definition.components_for_graph)
21
- graph.output( :png => filename )
24
+
25
+ if filename.start_with?('s3://')
26
+ content = graph.output( :png => String )
27
+ S3Writer.new(filename).write(content)
28
+ else
29
+ graph.output( :png => filename )
30
+ filename
31
+ end
22
32
  end
23
33
 
24
34
  end
@@ -0,0 +1,8 @@
1
+ require 'pipely/actions/graph_live_pipeline'
2
+ require 'pipely/actions/graph_file_pipeline'
3
+ require 'pipely/actions/list_live_pipelines'
4
+
5
+ module Pipely
6
+ module Actions
7
+ end
8
+ end
@@ -0,0 +1,39 @@
1
+ module Pipely
2
+ module Actions
3
+
4
+ # Graph a pipeline definition from a file.
5
+ #
6
+ class GraphFilePipeline
7
+
8
+ def initialize(options)
9
+ @options = options
10
+ end
11
+
12
+ def execute
13
+ puts "Generating #{output_file}"
14
+ Pipely.draw(definition_json, output_file)
15
+ end
16
+
17
+ private
18
+
19
+ def definition_json
20
+ File.open(@options.input_path).read
21
+ end
22
+
23
+ def output_base
24
+ @output_base ||= File.basename(@options.input_path,".*") + '.png'
25
+ end
26
+
27
+ def output_file
28
+ @output_file ||= if @options.output_path
29
+ File.join(@options.output_path, output_base)
30
+ else
31
+ output_base
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
39
+
@@ -0,0 +1,34 @@
1
+ module Pipely
2
+ module Actions
3
+
4
+ # Graph a deployed pipeline with live execution statuses.
5
+ #
6
+ class GraphLivePipeline
7
+
8
+ def initialize(options)
9
+ @options = options
10
+ end
11
+
12
+ def execute
13
+ live_pipeline = Pipely::LivePipeline.new(@options.pipeline_id)
14
+ live_pipeline.print_runs_report
15
+
16
+ outfile = if @options.latest_run
17
+ live_pipeline.render_latest_graph(@options.output_path)
18
+ else
19
+ live_pipeline.render_graphs(@options.output_path)
20
+ end
21
+
22
+ if @options.json_output
23
+ $stdout.puts({ :graph => outfile }.to_json)
24
+ elsif $stdout.tty?
25
+ $stdout.puts "Generated #{outfile}"
26
+ else
27
+ $stdout.puts outfile
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,38 @@
1
+ module Pipely
2
+ module Actions
3
+
4
+ # List currently deployed pipelines
5
+ #
6
+ class ListLivePipelines
7
+
8
+ def initialize(options)
9
+ @options = options
10
+ end
11
+
12
+ def execute
13
+ if @options.json_output
14
+ $stdout.puts pipeline_ids.to_json
15
+ else
16
+ $stdout.puts pipeline_ids.map { |pipeline|
17
+ [ pipeline['name'], pipeline['id'] ].join("\t")
18
+ }
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def pipeline_ids
25
+ ids = []
26
+
27
+ begin
28
+ result = Fog::AWS[:data_pipeline].list_pipelines
29
+ ids += result['pipelineIdList']
30
+ end while (result['hasMoreResults'] && result['marker'])
31
+
32
+ ids
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
@@ -33,13 +33,9 @@ module Pipely
33
33
  end
34
34
 
35
35
  def task_states_by_scheduled_start
36
- c = Fog::AWS[:data_pipeline]
37
- instances = c.query_objects(pipeline_id, 'INSTANCE')
38
- instance_details = c.describe_objects(pipeline_id, instances['ids'])
39
-
40
36
  task_states_by_scheduled_start = {}
41
37
 
42
- instance_details['pipelineObjects'].each do |pipeline_object|
38
+ all_instances.each do |pipeline_object|
43
39
  component_id = status = scheduled_start = nil
44
40
 
45
41
  pipeline_object['fields'].each do |field|
@@ -62,5 +58,32 @@ module Pipely
62
58
  task_states_by_scheduled_start
63
59
  end
64
60
 
61
+ private
62
+
63
+ def all_instances
64
+ c = Fog::AWS[:data_pipeline]
65
+
66
+ result = {}
67
+ pipeline_objects = []
68
+
69
+ begin
70
+ if result['marker']
71
+ marker = JSON.parse(result['marker'])['primary']
72
+ end
73
+
74
+ result = c.query_objects(
75
+ pipeline_id,
76
+ 'INSTANCE',
77
+ marker: result['marker']
78
+ )
79
+
80
+ instance_details = c.describe_objects(pipeline_id, result['ids'])
81
+ pipeline_objects += instance_details['pipelineObjects']
82
+
83
+ end while (result['hasMoreResults'] && result['marker'])
84
+
85
+ pipeline_objects
86
+ end
87
+
65
88
  end
66
89
  end
@@ -26,22 +26,28 @@ module Pipely
26
26
  RunsReport.new(@task_states_by_scheduled_start).print
27
27
  end
28
28
 
29
- def render_graphs
30
- @task_states_by_scheduled_start.each do |start, task_states|
31
- utc_time = Time.now.to_i
32
- formatted_start = start.gsub(/[:-]/, '').sub('T', '-')
29
+ def render_latest_graph(output_path=nil)
30
+ latest_start = @task_states_by_scheduled_start.keys.max
31
+ task_states = @task_states_by_scheduled_start[latest_start]
32
+ render_graph(latest_start, task_states, output_path)
33
+ end
33
34
 
34
- filename = "graphs/#{@pipeline_id}-#{formatted_start}-#{utc_time}.png"
35
+ def render_graphs(output_path=nil)
36
+ @task_states_by_scheduled_start.map do |start, task_states|
37
+ render_graph(start, task_states, output_path)
38
+ end
39
+ end
35
40
 
36
- if $stdout.tty?
37
- $stdout.puts "Generating #{filename}"
38
- else
39
- $stdout.puts filename
40
- end
41
+ private
41
42
 
42
- Pipely.draw(@definition_json, filename, task_states)
43
- end
43
+ def render_graph(start, task_states, output_path)
44
+ utc_time = Time.now.to_i
45
+ formatted_start = start.gsub(/[:-]/, '').sub('T', '-')
46
+
47
+ output_base = "#{@pipeline_id}-#{formatted_start}-#{utc_time}.png"
48
+ filename = File.join((output_path || 'graphs'), output_base)
44
49
 
50
+ Pipely.draw(@definition_json, filename, task_states)
45
51
  end
46
52
 
47
53
  end
@@ -0,0 +1,47 @@
1
+ require 'optparse'
2
+
3
+ module Pipely
4
+
5
+ # Options for running the CLI
6
+ #
7
+ class Options
8
+
9
+ attr_accessor :pipeline_id, :input_path, :output_path,
10
+ :verbose, :automatic_open, :json_output, :latest_run
11
+
12
+ def self.parse
13
+ options = Pipely::Options.new
14
+
15
+ OptionParser.new do |opts|
16
+ opts.banner = "Usage: pipely [options]"
17
+
18
+ opts.on("-p", "--pipeline-id PIPELINE_ID",
19
+ "ID of a live pipeline to visualize with live statuses") do |id|
20
+ options.pipeline_id = id
21
+ end
22
+
23
+ opts.on("-l", "--latest", "Graph only the latest run") do |latest|
24
+ options.latest_run = latest
25
+ end
26
+
27
+ opts.on("-i", "--input PATH",
28
+ "Path to a JSON pipeline definition file to visualize") do |input|
29
+ options.input_path = input
30
+ end
31
+
32
+ opts.on("-o", "--output PATH",
33
+ "Local or S3 path to write Graphviz PNG file(s)") do |output|
34
+ options.output_path = output
35
+ end
36
+
37
+ opts.on("-j", "--json", "Write STDOUT formatted as JSON") do |json|
38
+ options.json_output = json
39
+ end
40
+ end.parse!
41
+
42
+ options
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,33 @@
1
+ require 'fog/storage'
2
+
3
+ module Pipely
4
+
5
+ # Writes content from a String to an S3 path
6
+ #
7
+ class S3Writer
8
+
9
+ def initialize(s3_path)
10
+ uri = URI.parse(s3_path)
11
+ @host, @path = uri.host, uri.path.gsub(/^\//,'')
12
+ end
13
+
14
+ def directory
15
+ storage = Fog::Storage.new({ provider: 'AWS' })
16
+ directory = storage.directories.detect{ |d| d.key == @host }
17
+
18
+ directory or raise("Couldn't find S3 bucket '#{@host}'")
19
+ end
20
+
21
+ def write(content)
22
+ remote_file = directory.files.create({
23
+ :key => @path,
24
+ :body => content,
25
+ :public => true,
26
+ })
27
+
28
+ remote_file.public_url
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -1,3 +1,3 @@
1
1
  module Pipely
2
- VERSION = "0.3.0" unless defined?(::DataPipelineGraphviz::VERSION)
2
+ VERSION = "0.4.0" unless defined?(::DataPipelineGraphviz::VERSION)
3
3
  end
@@ -2,7 +2,7 @@ require 'pipely'
2
2
 
3
3
  describe Pipely do
4
4
  let(:definition_json) { stub }
5
- let(:filename) { stub }
5
+ let(:filename) { 'path/to/graph.png' }
6
6
  let(:definition) { stub }
7
7
 
8
8
  before do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pipely
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Gillooly
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-12 00:00:00.000000000 Z
11
+ date: 2014-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-graphviz
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 1.20.0
61
+ version: 1.21.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: 1.20.0
68
+ version: 1.21.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: unf
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -158,6 +158,10 @@ executables:
158
158
  extensions: []
159
159
  extra_rdoc_files: []
160
160
  files:
161
+ - lib/pipely/actions/graph_file_pipeline.rb
162
+ - lib/pipely/actions/graph_live_pipeline.rb
163
+ - lib/pipely/actions/list_live_pipelines.rb
164
+ - lib/pipely/actions.rb
161
165
  - lib/pipely/build/daily_scheduler.rb
162
166
  - lib/pipely/build/definition.rb
163
167
  - lib/pipely/build/environment_config.rb
@@ -174,8 +178,10 @@ files:
174
178
  - lib/pipely/fog_client.rb
175
179
  - lib/pipely/graph_builder.rb
176
180
  - lib/pipely/live_pipeline.rb
181
+ - lib/pipely/options.rb
177
182
  - lib/pipely/reference_list.rb
178
183
  - lib/pipely/runs_report.rb
184
+ - lib/pipely/s3_writer.rb
179
185
  - lib/pipely/shared_examples.rb
180
186
  - lib/pipely/tasks/definition.rb
181
187
  - lib/pipely/tasks/deploy.rb