farmstead 0.0.9 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3fc5cf26badb4c4d6936bf064c20e64560f6e5ed
4
- data.tar.gz: 4e8778dafcee5bfe2c27aad8be836fc987dc2e55
3
+ metadata.gz: 032071d2a61bf9d506341f24564fe0a2ae808e3e
4
+ data.tar.gz: 406e17d3e1ed534c9160d5f0bda42e0f98234390
5
5
  SHA512:
6
- metadata.gz: 182397b751e55d19c1a9a2fffb3f6f47c9f0ee84ef70807de1275005a165b277b3cec6360569afe1a95ef7a4c5787415fd7b0eb8e23bfde31d7885084bf0ab2c
7
- data.tar.gz: 49ac4a5933d3ef9d7ca016d70cf1a21af3cbbffc25f7da34d2757bfe100a9460ddf487b1e0e65814d1f4d4b510ddbae85d7eb84227dc99300fc97868f0942233
6
+ metadata.gz: 6cdbf29f46a55486b4db5bd64f602a6d5a65df193e36a30b1ae8f4595e516d50aa3f68d20fdc9692ed404b19bc321b66c53472f17022bfabfbfb70d4e5b5a037
7
+ data.tar.gz: 8d6e13d3641de498b9473586334f927fc8133275e7a3cdff53950068ad52f173908042a97ab45ce490cba606fdf8928dc7bb071230030177afefece080cefa7c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- farmstead (0.0.9)
4
+ farmstead (0.0.11)
5
5
  thor (~> 0.20.0)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/farmstead.svg)](https://badge.fury.io/rb/farmstead)
4
4
  [![Build Status](https://api.travis-ci.org/mastermindg/farmstead.svg?branch=master)](http://travis-ci.org/mastermindg/farmstead)
5
5
 
6
- Farmstead is a modular data pipeline platform. Farmstead makes creating and deploying a fully-functional data pipeline a snap. It is built on top of Rails/Ruby and uses Docker. This combination allows for a super-fast deployment and prototyping process.
6
+ Farmstead is a modular data pipeline platform. Farmstead makes creating and deploying a fully-functional data pipeline a snap. Farmstead uses containers to encapsulate the middleware which allows for a super-fast deployment and prototyping process.
7
7
 
8
8
 
9
9
  ## Table of Contents
@@ -38,8 +38,6 @@ To create a new Farmstead project:
38
38
 
39
39
  ```
40
40
  farmstead new myproject
41
- cd myproject
42
- farmstead start
43
41
  ```
44
42
 
45
43
  ### Configuration
@@ -60,17 +58,9 @@ An example configuration file is included.
60
58
 
61
59
  #### Configuration Options
62
60
 
63
- **Rails Authentication**
64
-
65
- There is optional Rails Authentication with AUTH0.
66
-
67
- **Rails Environment**
68
-
69
- The default environment is development but can be set to production (if you're ready).
70
-
71
61
  **Database**
72
62
 
73
- The default database is MySQL but can be set to anything that Rails can handle.
63
+ The default database is MySQL but can be set to either MySQL, Postgres, or SQLLite. Extensions will be available
74
64
 
75
65
  **Kafka**
76
66
 
@@ -103,29 +93,33 @@ farmstead new myproject -x kubernetes
103
93
 
104
94
  ## Architecture
105
95
 
106
- Kafka and Database ETL
96
+ Kafka and Database
97
+
98
+ ETL
107
99
 
108
- Presently only Dorothy is running Rails. The rest of the services are only running a Kafka consumer and producer. Eventually that will change.
100
+ * Extract
101
+ * Transform
102
+ * Load
109
103
 
110
- ### Scheduler - Glenda
104
+ All of the services are only running a Kafka consumer and producer. There is a Manager service that
111
105
 
112
- Glenda
106
+ **Classes:**
113
107
 
114
- ### Fertilize - Tinman
108
+ ### Farmstead::Manager
115
109
 
116
- Tinman
110
+ Task scheduling, batch processing, and general flow control. Exposes a very simple web service where you can pull logs and see the data in real-time.
117
111
 
118
- ### Harvest - Scarecrow
112
+ ### Farmstead::Extract
119
113
 
120
- Scarecrow
114
+ Extracts the data from the source.
121
115
 
122
- ### Mill - CowardlyLion
116
+ ### Farmstead::Transform
123
117
 
124
- Cowardlylion
118
+ Transforms one or more datasets.
125
119
 
126
- ### Serve - Dorothy
120
+ ### Farmstead::Load
127
121
 
128
- Dorothy
122
+ Loads the data into a database.
129
123
 
130
124
  ## License
131
125
 
@@ -134,7 +128,6 @@ MIT
134
128
 
135
129
  ## TODO
136
130
 
137
- 1. Find out how to create roles for Dorothy
131
+ 1. Database extensions
138
132
  2. Get Micro-services working
139
- 3. Figure out how to get Selenium working or if it's necessary (Selenium)
140
133
 
@@ -0,0 +1,7 @@
1
+ module MyProject
2
+ class Extracter < Farmstead::Extract
3
+ def hello
4
+ p "hello"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module MyProject
2
+ class Loader < Farmstead::Load
3
+ def hello
4
+ p "hello"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Primary script to kick off services in project
4
+ # Pass two arguments to this script
5
+ # 1st - the class you want to call
6
+ # 2nd - the method you want to call
7
+
8
+ dynamic_class = ARGV[0]
9
+ dynamic_method = ARGV[1]
10
+
11
+ # Extend Farmstead
12
+ require "farmstead"
13
+
14
+ # Load project classes
15
+ require_relative "extract/extracter"
16
+ require_relative "load/loader"
17
+ require_relative "transform/transformer"
18
+
19
+ module MyProject
20
+ include Farmstead
21
+ end
22
+
23
+ klass = Object.const_get "MyProject::#{dynamic_class}"
24
+ service = klass.new
25
+ service.send(dynamic_method)
@@ -0,0 +1,17 @@
1
+ - name: My Project
2
+ database:
3
+ - type: mysql
4
+ - MYSQL_ROOT_PASSWORD: Rc2$NE99p5%^
5
+ - MYSQL_DATABASE: farmstead
6
+ - MYSQL_USER: farmstead
7
+ - MYSQL_PASSWORD: farmstead
8
+ - MYSQL_HOST: mysql
9
+ kafka:
10
+ - advertise_from_local_ip: false
11
+ - advertised_ip: 192.168.1.2
12
+ - zookeeper_address: "zookeeper:2181"
13
+ - topics
14
+ - "Manage:1:1"
15
+ - "Extract:1:1"
16
+ - "Load:1:1"
17
+ - "Transform:1:1"
@@ -0,0 +1,7 @@
1
+ module MyProject
2
+ class Transformer < Farmstead::Transform
3
+ def hello
4
+ p "hello"
5
+ end
6
+ end
7
+ end
data/farmstead.gemspec CHANGED
@@ -20,7 +20,6 @@ Gem::Specification.new do |spec|
20
20
  f.match(%r{^(test|spec|features)/})
21
21
  end
22
22
 
23
- #spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
23
  spec.executables = ['farmstead']
25
24
  spec.require_paths = ["lib"]
26
25
 
data/lib/farmstead/cli.rb CHANGED
@@ -3,10 +3,16 @@ require "thor"
3
3
 
4
4
  module Farmstead
5
5
  class CLI < Thor
6
- class_option :verbose, aliases: "-v", type: "boolean", desc: "Be verbose"
6
+ class_option :verbose, aliases: "--v", type: "boolean", desc: "Be verbose"
7
7
  class_option :config, aliases: "-c", type: "string", desc: "Config file"
8
8
  class_option :database, aliases: "-d", type: "string", desc: "Database"
9
9
  class_option :deploy, aliases: "-x", type: "string", desc: "Deployment Method"
10
+
11
+ desc "version", "Get the gem version"
12
+ def version
13
+ puts "Farmstead #{Farmstead::VERSION}"
14
+ end
15
+
10
16
  desc "new project_name", "Create a new project"
11
17
  def new(project_name)
12
18
  project = Farmstead::Project.new
@@ -53,5 +59,7 @@ module Farmstead
53
59
 
54
60
  # desc "net COMMANDS", "Net control Module"
55
61
  # subcommand "net", Socialinvestigator::CLI::Net
62
+
63
+ map "-v" => "version"
56
64
  end
57
65
  end
@@ -1,5 +1,4 @@
1
- # Glenda - the Scheduler
2
- #
1
+ # Manager
3
2
  #
4
3
  # It works off of the DB when
5
4
  # 1) A new site is added
@@ -27,7 +26,7 @@
27
26
  # HINT: See .env
28
27
  # Every micro-service inherits the Service class
29
28
  module Farmstead
30
- class Glenda < Service
29
+ class Manager < Service
31
30
  # Runs on an infinite loop processing records
32
31
  # on MySQL DB and writing messages accordingly
33
32
  def producer
@@ -97,3 +96,4 @@ module Farmstead
97
96
  end
98
97
  end
99
98
  end
99
+
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Extract data from the source
4
+ #
5
+ # Runs a Consumer and it will automatically pick up
6
+ # messages from the Field Topic and do it's job
7
+ # and then send a message as a Producer to the Forest Topic
8
+ #
9
+ # Every micro-service inherits the Service class
10
+ module Farmstead
11
+ class Extract < Service
12
+ # Picks up JSON generated by WebDriver and save it to Forest topic
13
+ def producer
14
+ loop do
15
+ puts "Do something"
16
+ sleep 300
17
+ end
18
+ end
19
+
20
+ # Subscribed to the Field topic
21
+ # Works on message
22
+ def consumer
23
+ @consumer.subscribe('Field')
24
+ trap('TERM') { @consumer.stop }
25
+ @consumer.each_message do |message|
26
+ puts "Received: #{message.value}"
27
+ magic_work(message.value)
28
+ @consumer.mark_message_as_processed(message)
29
+ end
30
+ end
31
+
32
+ def magic_work(site)
33
+ hash = JSON.parse(site)
34
+ hash['scarecrow'] = 'true'
35
+ json = hash.to_json
36
+ puts "Writing: #{json}"
37
+ write_message(json, topic: 'Forest')
38
+ end
39
+ end
40
+ end
@@ -1,18 +1,18 @@
1
- # Scarecrow - the Harvester
2
- #
3
- # Scarecrow is responsible for extracting data from a source
1
+ # frozen_string_literal: true
2
+
3
+ # Load data into database
4
4
  #
5
- # Scarecrow is running as a Consumer and it will automatically pick up
5
+ # Runs a Consumer and it will automatically pick up
6
6
  # messages from the Field Topic and do it's job
7
7
  # and then send a message as a Producer to the Forest Topic
8
8
  #
9
9
  # Every micro-service inherits the Service class
10
10
  module Farmstead
11
- class Scarecrow < Service
11
+ class Load < Service
12
12
  # Picks up JSON generated by WebDriver and save it to Forest topic
13
13
  def producer
14
14
  loop do
15
- puts 'Do something'
15
+ puts "Do something"
16
16
  sleep 300
17
17
  end
18
18
  end
@@ -36,20 +36,6 @@ module Farmstead
36
36
  puts "Writing: #{json}"
37
37
  write_message(json, topic: 'Forest')
38
38
  end
39
-
40
- # Call the Site Class
41
- def call_class
42
- puts 'this'
43
- end
44
-
45
- def selenium
46
- browser = Watir::Browser.new :chrome
47
- browser.goto 'http://www.stackoverflow.com'
48
- puts browser.title
49
- # browser.text_field(title: 'Search').set 'Hello World!'
50
- # browser.button(type: 'submit').click
51
- # puts browser.title
52
- browser.quit
53
- end
54
39
  end
55
40
  end
41
+
@@ -1,15 +1,17 @@
1
- # CowardlyLion - the Miller
1
+ # frozen_string_literal: true
2
+
3
+ # Transform data
2
4
  #
3
- # Cowardlylion is responsible for arranging data into usable blocks
5
+ # Arrange data into usable blocks
4
6
  #
5
7
  #
6
- # CowardlyLion is running as a Consumer and it will automatically pick up
8
+ # Running as a Consumer and it will automatically pick up
7
9
  # messages from the Forest topic and do it's job and then send
8
10
  # a message as a Producer to the Road topic
9
11
  #
10
12
  # Every micro-service inherits the Service class
11
13
  module Farmstead
12
- class Cowardlylion #< Service
14
+ class Transform < Service
13
15
  # Does nothing...work is handled by magic_work
14
16
  def producer
15
17
  loop do
@@ -0,0 +1,7 @@
1
+ module MyProject
2
+ class Extracter < Farmstead::Extract
3
+ def hello
4
+ p "hello"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module MyProject
2
+ class Loader < Farmstead::Load
3
+ def hello
4
+ p "hello"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Primary script to kick off services in project
4
+ # Pass two arguments to this script
5
+ # 1st - the class you want to call
6
+ # 2nd - the method you want to call
7
+
8
+ dynamic_class = ARGV[0]
9
+ dynamic_method = ARGV[1]
10
+
11
+ # Extend Farmstead
12
+ require "farmstead"
13
+
14
+ # Load project classes
15
+ require_relative "extract/extracter"
16
+ require_relative "load/loader"
17
+ require_relative "transform/transformer"
18
+
19
+ module MyProject
20
+ include Farmstead
21
+ end
22
+
23
+ klass = Object.const_get "MyProject::#{dynamic_class}"
24
+ service = klass.new
25
+ service.send(dynamic_method)
@@ -0,0 +1,17 @@
1
+ - name: My Project
2
+ database:
3
+ - type: mysql
4
+ - MYSQL_ROOT_PASSWORD: Rc2$NE99p5%^
5
+ - MYSQL_DATABASE: farmstead
6
+ - MYSQL_USER: farmstead
7
+ - MYSQL_PASSWORD: farmstead
8
+ - MYSQL_HOST: mysql
9
+ kafka:
10
+ - advertise_from_local_ip: false
11
+ - advertised_ip: 192.168.1.2
12
+ - zookeeper_address: "zookeeper:2181"
13
+ - topics
14
+ - "Manage:1:1"
15
+ - "Extract:1:1"
16
+ - "Load:1:1"
17
+ - "Transform:1:1"
@@ -0,0 +1,7 @@
1
+ module MyProject
2
+ class Transformer < Farmstead::Transform
3
+ def hello
4
+ p "hello"
5
+ end
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module Farmstead
2
- VERSION = "0.0.9"
2
+ VERSION = "0.0.11"
3
3
  end
data/lib/farmstead.rb CHANGED
@@ -35,11 +35,10 @@ require "farmstead/version"
35
35
  require "farmstead/project"
36
36
  require "farmstead/cli"
37
37
  require "farmstead/service"
38
- require "farmstead/tinman"
39
- require "farmstead/cowardlylion"
40
- require "farmstead/glenda"
41
- require "farmstead/scarecrow"
42
- require "farmstead/tinman"
38
+ require "farmstead/manager"
39
+ require "farmstead/pipeline/extract"
40
+ require "farmstead/pipeline/transform"
41
+ require "farmstead/pipeline/load"
43
42
 
44
43
  module Farmstead
45
44
  # Your code goes here...
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: farmstead
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ken Jenney
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-31 00:00:00.000000000 Z
11
+ date: 2018-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -87,28 +87,33 @@ files:
87
87
  - LICENSE.txt
88
88
  - README.md
89
89
  - Rakefile
90
- - bin/console
91
90
  - bin/farmstead
92
- - bin/setup
93
- - examples/myproject.yml
91
+ - examples/myproject/extract/extracter.rb
92
+ - examples/myproject/load/loader.rb
93
+ - examples/myproject/myproject.rb
94
+ - examples/myproject/myproject.yml
95
+ - examples/myproject/transform/transformer.rb
94
96
  - farmstead.gemspec
95
97
  - lib/farmstead.rb
96
98
  - lib/farmstead/cli.rb
97
- - lib/farmstead/cowardlylion.rb
98
- - lib/farmstead/glenda.rb
99
+ - lib/farmstead/manager.rb
100
+ - lib/farmstead/pipeline/extract.rb
101
+ - lib/farmstead/pipeline/load.rb
102
+ - lib/farmstead/pipeline/transform.rb
99
103
  - lib/farmstead/project.rb
100
104
  - lib/farmstead/scaffold/.dockerignore.erb
101
105
  - lib/farmstead/scaffold/.env.erb
102
- - lib/farmstead/scaffold/Dockerfile-dorothy.erb
103
106
  - lib/farmstead/scaffold/Dockerfile.erb
104
107
  - lib/farmstead/scaffold/Gemfile.erb
105
- - lib/farmstead/scaffold/app/controllers/application_controller.rb.erb
106
108
  - lib/farmstead/scaffold/docker-compose.yml.erb
107
109
  - lib/farmstead/scaffold/exec.sh.erb
110
+ - lib/farmstead/scaffold/extract/extracter.rb.erb
111
+ - lib/farmstead/scaffold/load/loader.rb
112
+ - lib/farmstead/scaffold/project.rb.erb
113
+ - lib/farmstead/scaffold/project.yml.erb
108
114
  - lib/farmstead/scaffold/supervisord.conf.erb
109
- - lib/farmstead/scarecrow.rb
115
+ - lib/farmstead/scaffold/transform/transformer.rb
110
116
  - lib/farmstead/service.rb
111
- - lib/farmstead/tinman.rb
112
117
  - lib/farmstead/version.rb
113
118
  homepage: https://github.com/mastermindg/farmstead
114
119
  licenses:
data/bin/console DELETED
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "farmstead"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- # require "irb"
14
- # IRB.start(__FILE__)
15
-
16
- require "farmstead"
17
-
18
- Farmstead::CLI.start(ARGV)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
@@ -1,26 +0,0 @@
1
- - name: My Project
2
- rails:
3
- - authentication:
4
- - enable: true
5
- - AUTH0_CLIENT_ID: myclientid
6
- - AUTH0_CLIENT_SECRET: myclientsecret
7
- - AUTH0_DOMAIN: myauth0domain
8
- - AUTH0_DOMAIN: http://localhost:3000/auth/auth0/callback
9
- - AUTH0_AUDIENCE:
10
- - environment: development
11
- database:
12
- - type: mysql
13
- - MYSQL_ROOT_PASSWORD: Rc2$NE99p5%^
14
- - MYSQL_DATABASE: farmstead
15
- - MYSQL_USER: farmstead
16
- - MYSQL_PASSWORD: farmstead
17
- - MYSQL_HOST: mysql
18
- kafka:
19
- - advertise_from_local_ip: false
20
- - advertised_ip: 192.168.1.2
21
- - zookeeper_address: "zookeeper:2181"
22
- - topics
23
- - "Wood:1:1"
24
- - "Field:1:1"
25
- - "Forest:1:1"
26
- - "Road:1:1"
@@ -1,24 +0,0 @@
1
- FROM ruby:2.4.1
2
-
3
- RUN apt-get update -qq && \
4
- apt-get install -y build-essential \
5
- libpq-dev \
6
- nodejs \
7
- telnet \
8
- bash \
9
- supervisor \
10
- vim \
11
- xterm \
12
- ca-certificates \
13
- unzip && \
14
- rm -rf /var/cache/apk/*
15
-
16
- ## Setup Rails
17
-
18
- RUN gem install rails && rails new <%= @name %> <% if @database %>-d <%= @database %><% end %>
19
- WORKDIR /<%= @name %>
20
- ADD app/* /<%= @name %>/app
21
-
22
- EXPOSE 3000
23
-
24
- CMD /<%= @name %>/bin/rails s -b 0.0.0.0
@@ -1,6 +0,0 @@
1
- class ApplicationController < ActionController::Base
2
- # Prevent CSRF attacks by raising an exception.
3
- # For APIs, you may want to use :null_session instead.
4
- protect_from_forgery with: :exception
5
- end
6
-
@@ -1,49 +0,0 @@
1
- # Tinman - the Fertilizer
2
- #
3
- # Tinman is responsible for analyzing a site for changes
4
- # and updating site configs
5
- #
6
- # None of the logic has actually been built and
7
- # this may require some AI but for now it's
8
- # just responding that everything is OK
9
- #
10
- # Tinman is running as a Consumer to the Wood topic and it will automatically
11
- # pick up the message, do it's job and then send a message
12
- # as a Producer to the Field topic
13
- #
14
- # Every micro-service inherits the Service class
15
- module Farmstead
16
- class Tinman < Service
17
- # Doing nothing...for now
18
- # thi is handled by magic_work
19
- def producer
20
- loop do
21
- puts 'Doing nothing'
22
- sleep 300
23
- end
24
- end
25
-
26
- # Subscribed to the Wood topic
27
- # Works on message
28
- def consumer
29
- @consumer.subscribe('Wood')
30
- trap('TERM') { @consumer.stop }
31
- @consumer.each_message do |message|
32
- puts "Received: #{message.value}"
33
- magic_work(message.value)
34
- @consumer.mark_message_as_processed(message)
35
- end
36
- end
37
-
38
- # Do the magic work to determine if the site has changed
39
- # and update the config
40
- # Returns JSON String
41
- def magic_work(site)
42
- hash = JSON.parse(site)
43
- hash['tinman'] = 'true'
44
- json = hash.to_json
45
- puts "Writing: #{json}"
46
- write_message(json, topic: 'Field')
47
- end
48
- end
49
- end