full360-sequencer 0.1.3 → 0.2.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
  SHA256:
3
- metadata.gz: 54bca4472a18632b312e84aff4c3ca5958053645dca8860f579c27e257689337
4
- data.tar.gz: 024a6bad17c794fe021cfd31df13a03ada093aa4c0c12c3dfd7432e38b43a518
3
+ metadata.gz: b89f369df62f5fa73c8eef3b7597596bcbe052026761aed9e9c9b1b23bc0fb90
4
+ data.tar.gz: bb4a599e8df5d9cd2410fe5d91fe15a68648731f1bf33c3979708f6dc3f822ed
5
5
  SHA512:
6
- metadata.gz: 04e30b01ccbb05f4622d1596c37cbff99ad15cabd7ab8e6bd8bc1906a46482a35e7f1cc5fc51588e66b281a71ea3e31b4ab945b01abe5650cbf30eb777117c16
7
- data.tar.gz: 510b7447b7182e6a746d6584a48ea4949aeeeb320a222bc0605e4ebcae93729f56928dd301d2ae3fa01a54843364a9f5672c1f2526197374b4425f8a0fd57015
6
+ metadata.gz: 7df9df844dabb0d75c55971cc09da599b34ca4796fb670e6a49209ba652bfffdd81d290b9c35c516d9f8513d097a0cec8305eeb739eb68acfeb2a5ae5770c336
7
+ data.tar.gz: 1585bb1dadb01907286f2c7deab022d8f69d7fc2dec9ad51aeaf860885a74b624bffe48677ae159779eb8dd5faee383b19ed93f1f38c03b3b9978feb8c65e02d
@@ -1,17 +1,14 @@
1
1
  name: Release Gem
2
2
 
3
3
  on:
4
- workflow_run:
5
- workflows: ["CI Test"]
6
- types: [completed]
7
- branches:
8
- - master
4
+ push:
9
5
  tags:
10
- - v*
6
+ - "v*"
11
7
 
12
8
  jobs:
13
9
  release:
14
10
  runs-on: ubuntu-latest
11
+
15
12
  steps:
16
13
  # Checkout code if release was created
17
14
  - uses: actions/checkout@v2
@@ -33,3 +30,69 @@ jobs:
33
30
  gem push *.gem
34
31
  env:
35
32
  RUBYGEMS_API_KEY: "${{secrets.RUBYGEMS_API_KEY}}"
33
+
34
+ docker-jruby:
35
+ runs-on: ubuntu-latest
36
+ needs: release
37
+
38
+ steps:
39
+ - name: Checkout
40
+ uses: actions/checkout@v2
41
+
42
+ - name: Set up Docker Buildx
43
+ uses: docker/setup-buildx-action@v1
44
+
45
+ - name: Login to DockerHub
46
+ uses: docker/login-action@v1
47
+ with:
48
+ username: ${{ secrets.DOCKER_HUB_USERNAME }}
49
+ password: ${{ secrets.DOCKER_HUB_TOKEN }}
50
+
51
+ - name: Extract tag name
52
+ id: tag
53
+ uses: actions/github-script@0.2.0
54
+ with:
55
+ script: return context.payload.ref.replace(/\/refs\/tags\//, '')
56
+
57
+ - name: Build JRuby image
58
+ uses: docker/build-push-action@v2
59
+ with:
60
+ file: ./Dockerfile.jruby
61
+ pull: true
62
+ push: true
63
+ tags: |
64
+ full360/sequencer:jruby-latest
65
+ full360/sequencer:${{ steps.tag.outputs.result }}-jruby-latest
66
+
67
+ docker-ruby:
68
+ runs-on: ubuntu-latest
69
+ needs: release
70
+
71
+ steps:
72
+ - name: Checkout
73
+ uses: actions/checkout@v2
74
+
75
+ - name: Set up Docker Buildx
76
+ uses: docker/setup-buildx-action@v1
77
+
78
+ - name: Login to DockerHub
79
+ uses: docker/login-action@v1
80
+ with:
81
+ username: ${{ secrets.DOCKER_HUB_USERNAME }}
82
+ password: ${{ secrets.DOCKER_HUB_TOKEN }}
83
+
84
+ - name: Extract tag name
85
+ id: tag
86
+ uses: actions/github-script@0.2.0
87
+ with:
88
+ script: return context.payload.ref.replace(/\/refs\/tags\//, '')
89
+
90
+ - name: Build Ruby image
91
+ uses: docker/build-push-action@v2
92
+ with:
93
+ file: ./Dockerfile.ruby
94
+ pull: true
95
+ push: true
96
+ tags: |
97
+ full360/sequencer:ruby-latest
98
+ full360/sequencer:${{ steps.tag.outputs.result }}-ruby-latest
@@ -9,7 +9,7 @@ jobs:
9
9
  matrix:
10
10
  os: [ubuntu-latest, macos-latest]
11
11
  # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0'
12
- ruby: ["2.7", "3.0", "jruby-9.2.19.0", "jruby-9.3.0.0"]
12
+ ruby: ["2.7", "jruby-9.2.19.0", "jruby-9.3.0.0"]
13
13
  runs-on: ${{ matrix.os }}
14
14
 
15
15
  if: "!contains(github.event.head_commit.message, '[ci skip]')"
data/CHANGELOG.md CHANGED
@@ -10,6 +10,29 @@ Versioning](http://semver.org/spec/v2.0.0.html).
10
10
  ### Changed
11
11
  ### Removed
12
12
 
13
+ ## 0.2.0
14
+ ### Added
15
+ - Add Docker image for Ruby and JRuby that will get triggered after the release.
16
+ ### Changed
17
+ - Refactor the code to make it easier to read and modify.
18
+ - Update the AWS SDK for ECS to V3.
19
+ - Fix a missing logger dependency in the bin/sequencer code.
20
+ ### Removed
21
+ - Tests for Ruby 3.0 as they were failing for an unknown reason and I couldn't
22
+ reproduce locally.
23
+
24
+ ## 0.1.3
25
+ ### Added
26
+ - Fix release workflow.
27
+ ### Changed
28
+ ### Removed
29
+
30
+ ## 0.1.2
31
+ ### Added
32
+ - Fix release workflow.
33
+ ### Changed
34
+ ### Removed
35
+
13
36
  ## 0.1.1
14
37
  ### Added
15
38
  - Workflows dependable.
data/Dockerfile.jruby ADDED
@@ -0,0 +1,23 @@
1
+ FROM jruby:9.2-jre8
2
+
3
+ # Should be more than sufficient for transforms without large recordset
4
+ # operations.
5
+ ENV JRUBY_OPTS=-J-Xmx1024m
6
+
7
+ RUN apt-get update \
8
+ && apt-get install -y --no-install-recommends \
9
+ unzip \
10
+ ca-certificates \
11
+ awscli \
12
+ && update-ca-certificates \
13
+ && rm -rf /var/lib/apt/lists/*
14
+
15
+ #set time zone
16
+ RUN mv /etc/localtime /etc/localtime.bak ; ln -s /usr/share/zoneinfo/UTC /etc/localtime
17
+
18
+ RUN gem install full360-sequencer
19
+
20
+ # this is the entry point
21
+ ADD entrypoint.sh /usr/sbin/runner.sh
22
+ RUN chmod 755 /usr/sbin/runner.sh
23
+ ENTRYPOINT ["/usr/sbin/runner.sh"]
data/Dockerfile.ruby ADDED
@@ -0,0 +1,21 @@
1
+ FROM ruby:2.7-alpine
2
+
3
+ # Install required packages
4
+ RUN apk add --no-cache \
5
+ unzip \
6
+ ca-certificates \
7
+ bash \
8
+ wget \
9
+ curl \
10
+ aws-cli \
11
+ && update-ca-certificates \
12
+
13
+ #set time zone
14
+ RUN mv /etc/localtime /etc/localtime.bak ; ln -s /usr/share/zoneinfo/UTC /etc/localtime
15
+
16
+ RUN gem install full360-sequencer
17
+
18
+ # this is the entry point
19
+ ADD entrypoint.sh /usr/sbin/runner.sh
20
+ RUN chmod 755 /usr/sbin/runner.sh
21
+ ENTRYPOINT ["/usr/sbin/runner.sh"]
data/Gemfile.lock CHANGED
@@ -1,20 +1,22 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- full360-sequencer (0.1.3)
5
- aws-sdk (~> 2.9)
4
+ full360-sequencer (0.2.0)
5
+ aws-sdk-ecs (~> 1.85)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
10
  aws-eventstream (1.2.0)
11
- aws-sdk (2.11.632)
12
- aws-sdk-resources (= 2.11.632)
13
- aws-sdk-core (2.11.632)
14
- aws-sigv4 (~> 1.0)
11
+ aws-partitions (1.509.0)
12
+ aws-sdk-core (3.121.1)
13
+ aws-eventstream (~> 1, >= 1.0.2)
14
+ aws-partitions (~> 1, >= 1.239.0)
15
+ aws-sigv4 (~> 1.1)
15
16
  jmespath (~> 1.0)
16
- aws-sdk-resources (2.11.632)
17
- aws-sdk-core (= 2.11.632)
17
+ aws-sdk-ecs (1.85.0)
18
+ aws-sdk-core (~> 3, >= 3.120.0)
19
+ aws-sigv4 (~> 1.1)
18
20
  aws-sigv4 (1.4.0)
19
21
  aws-eventstream (~> 1, >= 1.0.2)
20
22
  coderay (1.1.3)
@@ -47,4 +49,4 @@ DEPENDENCIES
47
49
  rake (~> 12)
48
50
 
49
51
  BUNDLED WITH
50
- 2.2.27
52
+ 2.2.28
data/README.md CHANGED
@@ -94,4 +94,11 @@ Releasing a new version of the Gem requires a few steps:
94
94
  - Create a Git tag that matches the version number in `version.rb`
95
95
  - Example: `git tag -m "Version 1.0.0" v1.0.0`
96
96
 
97
+ ## Running the Sequencer from Docker
98
+
99
+ Pass the following environment variables to the container at runtime:
100
+
101
+ * `SEQUENCER_YAML_S3_PATH` - s3:// path to the yaml configuration file.
102
+ * `AWS_REGION` - AWS region in which you are running the container.
103
+
97
104
  [ref]: http://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_RunTask.html
data/bin/sequencer CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require "logger"
3
4
  require "full360-sequencer"
4
5
 
5
6
  config_file = ARGV[0]
@@ -14,7 +15,7 @@ def logger
14
15
  end
15
16
 
16
17
  def sequencer_version
17
- Gem.loaded_specs["full360-sequencer"].version
18
+ Full360::Sequencer::VERSION
18
19
  end
19
20
 
20
21
  begin
@@ -22,20 +23,20 @@ begin
22
23
  logger.level = ENV["SEQUENCER_LOG_DEBUG"] ? Logger::DEBUG : Logger::INFO
23
24
 
24
25
  if config_file == nil
25
- logger.error("SEQUENCER_ERROR")
26
- logger.error("YAML file not provided... exiting with error code 1")
26
+ logger.error("SEQUENCER_ERROR: YAML file not provided... exiting with error code 1")
27
27
  exit 1
28
28
  else
29
- r = Full360::Sequencer::Runner.new(logger)
30
- r.config_from_file(config_file)
31
- r.sleep_between_checks = ENV["SEQUENCER_SLEEP_BETWEEN_CHECKS"].to_i if ENV["SEQUENCER_SLEEP_BETWEEN_CHECKS"]
32
- r.run
29
+ sleep_between_checks = ENV.fetch("SEQUENCER_SLEEP_BETWEEN_CHECKS", 5).to_i
30
+
31
+ Full360::Sequencer::Runner.new(sleep_between_checks, logger).tap do |runner|
32
+ runner.config_from_file(config_file)
33
+ runner.run
34
+ end
33
35
  end
34
36
  logger.info("all steps succeeded... exiting with code 0")
35
37
  exit 0
36
38
  rescue => e
37
- logger.error("SEQUENCER_ERROR")
38
- logger.error(e.message)
39
+ logger.error("SEQUENCER_ERROR: #{e.message}")
39
40
  e.backtrace.each { |r| logger.error(r) }
40
41
  logger.error("failure... exiting with code 1")
41
42
  exit 1
data/entrypoint.sh ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+
3
+ if [ -n "$AWS_REGION" ]
4
+ then
5
+ aws s3 cp $SEQUENCER_YAML_S3_PATH /sequencer/file.yml --region $AWS_REGION
6
+ else
7
+ aws s3 cp $SEQUENCER_YAML_S3_PATH /sequencer/file.yml
8
+ fi
9
+
10
+ sequencer /sequencer/file.yml
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  # Make it Ruby 2+ only
26
26
  spec.required_ruby_version = ">= 2.0"
27
27
 
28
- spec.add_runtime_dependency "aws-sdk", "~> 2.9"
28
+ spec.add_runtime_dependency "aws-sdk-ecs", "~> 1.85"
29
29
 
30
30
  # development dependencies
31
31
  spec.add_development_dependency "minitest", "~> 5.9"
@@ -1,95 +1,101 @@
1
- require "aws-sdk"
2
1
  require "logger"
2
+ require "aws-sdk-ecs"
3
3
 
4
4
  module Full360
5
5
  module Sequencer
6
6
  class RunECSTask < RunTaskBase
7
- def initialize(task_name, params, logger = nil)
8
- @logger = logger ? logger : Logger.new(STDOUT)
9
- @task_name = task_name
10
- @params = params["parameters"]
11
- @params = keys_to_symbol(@params)
12
- @cluster = @params[:cluster]
13
- end
7
+ attr_accessor :task_name
8
+ attr_accessor :params
9
+ attr_accessor :ecs_client
10
+ attr_accessor :logger
14
11
 
15
- def keys_to_symbol(params)
16
- # replaces string keys with symbol keys
17
- # required by AWS SDK
18
- if params.is_a?(Hash)
19
- params.inject({}){ |memo,(k,v)| memo[k.to_sym] = v; memo }
20
- else
21
- nil
22
- end
12
+ attr_reader :cluster
13
+ attr_reader :task_arn
14
+ attr_reader :start_time
15
+
16
+ def initialize(task_name, params, ecs_client = nil, logger = nil)
17
+ @logger = logger ||= Logger.new(STDOUT)
18
+ @ecs_client = ecs_client ||= Aws::ECS::Client.new
19
+ @task_name = task_name
20
+ @params = params[:parameters]
21
+ @cluster = self.params[:cluster]
23
22
  end
24
23
 
25
24
  def run_task
26
- @logger.info("starting ECS task #{@task_name}")
25
+ logger.info("starting ECS task #{task_name}")
26
+
27
27
  resp = ecs_run_task
28
- @task_arn = resp.tasks[0].task_arn
29
- @logger.info("#{@task_name} task created #{@task_arn} on cluster #{@cluster}")
28
+ @task_arn = resp.tasks.first.task_arn
29
+
30
+ logger.info("#{task_name} task created #{task_arn} on cluster #{cluster}")
30
31
  end
31
32
 
32
33
  def ecs_run_task
33
- @logger.debug("creating AWS client for ECS task #{@task_name}...")
34
- @ecs_client = ::Aws::ECS::Client.new
35
- @logger.debug("running ECS task #{@task_name}...")
36
- @start_time = Time.new
37
- resp = @ecs_client.run_task(@params)
38
- return resp
34
+ logger.debug("running ECS task #{task_name}...")
35
+ @start_time = Time.new.utc
36
+
37
+ resp = ecs_client.run_task(params)
38
+ resp
39
39
  rescue => e
40
- @logger.error("SEQUENCER_ERROR")
41
- @logger.error("error creating ECS task...")
42
- @logger.error("response from ECS: #{resp}")
40
+ logger.error("SEQUENCER_ERROR: response from ECS #{resp}")
43
41
  raise e
44
42
  end
45
43
 
46
44
  def ecs_describe_tasks
47
- @ecs_client.describe_tasks(
45
+ ecs_client.describe_tasks(
48
46
  {
49
- cluster: @cluster,
50
- tasks: [@task_arn] # required
47
+ cluster: cluster,
48
+ tasks: [task_arn],
51
49
  }
52
50
  )
53
51
  end
54
52
 
55
53
  def completed?
56
54
  retries ||= 0
55
+
57
56
  resp = ecs_describe_tasks
58
57
  status = last_task_status(resp)
59
- @logger.info("#{@task_name} : #{@task_arn} current status: #{status}")
58
+
59
+ logger.info("#{task_name}: #{task_arn} current status: #{status}")
60
+
61
+ completed = false
62
+
60
63
  if status == "STOPPED"
61
- @logger.info("#{@task_name} completed in #{Time.new - @start_time} seconds")
64
+ logger.info("#{task_name} completed in #{Time.new.utc - start_time} seconds")
62
65
  # parse exit_code(s) and return completion
63
66
  @success = determine_success(resp)
64
- return true
67
+ completed = true
65
68
  end
66
- false
69
+
70
+ completed
67
71
  rescue => e
68
- @logger.warn(e.message)
69
- @logger.warn("task completion check failed, trying again ##{ retries }")
72
+ logger.warn(e.message)
73
+ logger.warn("task completion check failed, trying again ##{retries}")
74
+
70
75
  sleep 10*retries
76
+
71
77
  retry if (retries += 1) < 3
72
78
 
73
- @logger.error("SEQUENCER_ERROR")
74
- @logger.error(e.message)
75
- e.backtrace.each { |r| @logger.error(r) }
79
+ logger.error("SEQUENCER_ERROR: #{e.message}")
80
+ e.backtrace.each { |r| logger.error(r) }
76
81
  end
77
82
 
78
83
  # parses last status from aws API response
79
84
  def last_task_status(resp)
80
- resp.tasks[0].last_status
85
+ resp.tasks.first.last_status
81
86
  end
82
87
 
83
88
  # success is determined by all containers having zero exit code
84
89
  def determine_success(resp)
85
90
  success = true
86
- resp.tasks[0].containers.each do |c|
87
- @logger.info("#{@task_name} : container #{c.name} #{c.container_arn} completed with exit_code #{c.exit_code}")
88
- if c.exit_code != 0
89
- # we had a problem!
90
- success = false
91
- end
91
+
92
+ resp.tasks.first.containers.each do |c|
93
+ logger.info("#{task_name}: container #{c.name} #{c.container_arn} completed with exit_code #{c.exit_code}")
94
+
95
+ # we had a problem!
96
+ success = false if c.exit_code != 0
92
97
  end
98
+
93
99
  success
94
100
  end
95
101
  end
@@ -1,17 +1,22 @@
1
1
  require "yaml"
2
2
  require "logger"
3
+ require "full360_sequencer/run_ecs_task"
3
4
 
4
5
  module Full360
5
6
  module Sequencer
6
7
  class Runner
7
8
  attr_accessor :sleep_between_checks
8
- attr_accessor :config
9
+ attr_accessor :logger
9
10
 
10
- def initialize(logger = nil)
11
- @logger = logger ? logger : Logger.new(STDOUT)
11
+ attr_reader :config
12
12
 
13
- # default 5 seconds between completed? checks
14
- @sleep_between_checks = 5
13
+ # Initializes the class
14
+ # @params sleep_between_checks [Int]
15
+ # @params logger [Logger]
16
+ # @return [Full360::Sequencer::Runner]
17
+ def initialize(sleep_between_checks, logger = nil)
18
+ @sleep_between_checks = sleep_between_checks
19
+ @logger = logger ||= Logger.new(STDOUT)
15
20
  end
16
21
 
17
22
  def config_from_file(yaml_path)
@@ -20,28 +25,34 @@ module Full360
20
25
 
21
26
  def run_task_class(task_type_string)
22
27
  case task_type_string
23
- when "ecs_task" then Full360::Sequencer::RunECSTask
24
- else nil
28
+ when "ecs_task"
29
+ Full360::Sequencer::RunECSTask
30
+ else
31
+ nil
25
32
  end
26
33
  end
27
34
 
28
35
  def run
29
- @config.each do |params|
36
+ config.each do |params|
30
37
  this_task_name = task_name(params)
31
- this_task = run_task_class(params[this_task_name]["type"]).new(
38
+
39
+ this_task = run_task_class(params[this_task_name][:type]).new(
32
40
  this_task_name,
33
41
  params[this_task_name]
34
42
  )
43
+
35
44
  this_task.run_task
45
+
36
46
  until this_task.completed?
37
- sleep @sleep_between_checks
47
+ sleep sleep_between_checks
38
48
  end
49
+
39
50
  raise "task failed error" unless this_task.success
40
51
  end
41
52
  rescue => e
42
- @logger.error("SEQUENCER_ERROR")
43
- @logger.error(e.message)
44
- e.backtrace.each { |r| @logger.error(r) }
53
+ logger.error("SEQUENCER_ERROR: #{e.message}")
54
+
55
+ e.backtrace.each { |r| logger.error(r) }
45
56
  raise e
46
57
  end
47
58
 
@@ -49,14 +60,20 @@ module Full360
49
60
  params.keys.first
50
61
  end
51
62
 
52
- def parse_config_file(yaml_path)
53
- YAML.load_file(yaml_path)
54
- end
55
-
56
63
  def config_valid?(config)
57
64
  return false unless config.is_a? Array
58
65
  true
59
66
  end
67
+
68
+ private
69
+
70
+ # parse_config_file reads and parses the configuration file and returns
71
+ # an array of hashes with symbolize keys ready to consume.
72
+ # @params yaml_path [String]
73
+ # @return [Array]
74
+ def parse_config_file(yaml_path)
75
+ YAML.safe_load(File.read(yaml_path), symbolize_names: true)
76
+ end
60
77
  end
61
78
  end
62
79
  end
@@ -1,5 +1,5 @@
1
1
  module Full360
2
2
  module Sequencer
3
- VERSION = "0.1.3".freeze
3
+ VERSION = "0.2.0".freeze
4
4
  end
5
5
  end
@@ -1,3 +1,5 @@
1
+ require "logger"
2
+
1
3
  # Autoload all gem classes
2
4
  module Full360
3
5
  module Sequencer
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: full360-sequencer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Full 360 Group
@@ -11,19 +11,19 @@ cert_chain: []
11
11
  date: 2017-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: aws-sdk
14
+ name: aws-sdk-ecs
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.9'
19
+ version: '1.85'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.9'
26
+ version: '1.85'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -78,6 +78,8 @@ files:
78
78
  - ".github/workflows/test.yml"
79
79
  - ".gitignore"
80
80
  - CHANGELOG.md
81
+ - Dockerfile.jruby
82
+ - Dockerfile.ruby
81
83
  - Gemfile
82
84
  - Gemfile.lock
83
85
  - LICENSE
@@ -85,6 +87,7 @@ files:
85
87
  - Rakefile
86
88
  - bin/console
87
89
  - bin/sequencer
90
+ - entrypoint.sh
88
91
  - full360-sequencer.gemspec
89
92
  - lib/full360-sequencer.rb
90
93
  - lib/full360_sequencer.rb