obscured-heartbeat 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ae2d04d162ad5089169eca9fa8d2e9a9a90a9a16d0974c2ae16ec20ed8952c13
4
+ data.tar.gz: a20d2f5ede017743cb53f969e3aa38dba0f18762ab64149dea46f4febd4abe5e
5
+ SHA512:
6
+ metadata.gz: 8a7b1ab7fbed3de4ce68b808271aa5f6bb4221925cc0e9fc36daf4865149b5829fe451dc5e9a4e4fdb3f6174d0221d9c39dd78820b5885f26262daab9063b7b4
7
+ data.tar.gz: 66a78de3328732348e182b7a67de67aa12164596d2c0af6f57c9dcc0191cc79fbd16850653dcc1397c98c48701a2fd1bad764042c03f4cb5bf2fb8bb140ecb9d
data/.codeclimate.yml ADDED
@@ -0,0 +1,28 @@
1
+ version: "2"
2
+ checks:
3
+ complex-logic:
4
+ config:
5
+ threshold: 10
6
+ file-lines:
7
+ enabled: false
8
+ method-complexity:
9
+ config:
10
+ threshold: 15
11
+ method-lines:
12
+ config:
13
+ threshold: 250
14
+ similar-code:
15
+ enabled: false
16
+ plugins:
17
+ rubocop:
18
+ enabled: true
19
+ channel: rubocop-0-71
20
+ coffeelint:
21
+ enabled: true
22
+ eslint:
23
+ enabled: true
24
+ csslint:
25
+ enabled: true
26
+ exclude_patterns:
27
+ - "tests/"
28
+ - "spec/"
@@ -0,0 +1,29 @@
1
+ name: Ruby Gem
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ build:
11
+ name: Build + Publish
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - uses: actions/checkout@v2
16
+ - name: Set up Ruby 2.6
17
+ uses: actions/setup-ruby@v1
18
+ with:
19
+ ruby-version: 2.6.x
20
+ - name: Publish to RubyGems
21
+ run: |
22
+ mkdir -p $HOME/.gem
23
+ touch $HOME/.gem/credentials
24
+ chmod 0600 $HOME/.gem/credentials
25
+ printf -- "---\n:rubygems_api_key: ${RUBYGEMS_AUTH_TOKEN}\n" > $HOME/.gem/credentials
26
+ gem build *.gemspec
27
+ gem push *.gem
28
+ env:
29
+ RUBYGEMS_AUTH_TOKEN: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ .idea
2
+ .idea/
3
+ coverage/
data/.rubocop.yml ADDED
@@ -0,0 +1,14 @@
1
+ Metrics/AbcSize:
2
+ Max: 50
3
+ Metrics/ClassLength:
4
+ Enabled: false
5
+ Metrics/CyclomaticComplexity:
6
+ Max: 15
7
+ Metrics/LineLength:
8
+ Enabled: false
9
+ Metrics/MethodLength:
10
+ Enabled: false
11
+ Metrics/PerceivedComplexity:
12
+ Max: 15
13
+ Naming/FileName:
14
+ Enabled: false
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ obscured-heartbeat
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.7.2
data/.simplecov ADDED
@@ -0,0 +1,4 @@
1
+ SimpleCov.start do
2
+ add_filter 'version'
3
+ add_filter '/spec/'
4
+ end
data/.travis.yml ADDED
@@ -0,0 +1,17 @@
1
+ env:
2
+ global:
3
+ - CC_TEST_REPORTER_ID=4a1a54eeae5b7c8b3f49b4164c7ed1c9042bee5b0e734d0283ac61294b006cfa
4
+ language: ruby
5
+ bundler_args: --with development
6
+ rvm:
7
+ - 2.6.3
8
+ services:
9
+ - mongodb
10
+ before_script:
11
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
12
+ - chmod +x ./cc-test-reporter
13
+ - ./cc-test-reporter before-build
14
+ script:
15
+ - bundle exec rspec
16
+ after_script:
17
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'http://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in obscured-heartbeat.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,71 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ obscured-heartbeat (1.0.0)
5
+ activesupport
6
+ mongoid
7
+ mongoid_search
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ activemodel (6.1.3)
13
+ activesupport (= 6.1.3)
14
+ activesupport (6.1.3)
15
+ concurrent-ruby (~> 1.0, >= 1.0.2)
16
+ i18n (>= 1.6, < 2)
17
+ minitest (>= 5.1)
18
+ tzinfo (~> 2.0)
19
+ zeitwerk (~> 2.3)
20
+ bson (4.12.0)
21
+ concurrent-ruby (1.1.8)
22
+ diff-lcs (1.4.4)
23
+ docile (1.3.4)
24
+ factory_bot (6.1.0)
25
+ activesupport (>= 5.0.0)
26
+ fast-stemmer (1.0.2)
27
+ i18n (1.8.9)
28
+ concurrent-ruby (~> 1.0)
29
+ minitest (5.14.4)
30
+ mongo (2.14.0)
31
+ bson (>= 4.8.2, < 5.0.0)
32
+ mongoid (7.2.1)
33
+ activemodel (>= 5.1, < 6.2)
34
+ mongo (>= 2.10.5, < 3.0.0)
35
+ mongoid_search (0.4.0)
36
+ fast-stemmer (~> 1.0.0)
37
+ mongoid (>= 5.0.0)
38
+ rspec (3.10.0)
39
+ rspec-core (~> 3.10.0)
40
+ rspec-expectations (~> 3.10.0)
41
+ rspec-mocks (~> 3.10.0)
42
+ rspec-core (3.10.0)
43
+ rspec-support (~> 3.10.0)
44
+ rspec-expectations (3.10.0)
45
+ diff-lcs (>= 1.2.0, < 2.0)
46
+ rspec-support (~> 3.10.0)
47
+ rspec-mocks (3.10.0)
48
+ diff-lcs (>= 1.2.0, < 2.0)
49
+ rspec-support (~> 3.10.0)
50
+ rspec-support (3.10.0)
51
+ simplecov (0.21.2)
52
+ docile (~> 1.1)
53
+ simplecov-html (~> 0.11)
54
+ simplecov_json_formatter (~> 0.1)
55
+ simplecov-html (0.12.3)
56
+ simplecov_json_formatter (0.1.2)
57
+ tzinfo (2.0.4)
58
+ concurrent-ruby (~> 1.0)
59
+ zeitwerk (2.4.2)
60
+
61
+ PLATFORMS
62
+ ruby
63
+
64
+ DEPENDENCIES
65
+ factory_bot
66
+ obscured-heartbeat!
67
+ rspec
68
+ simplecov
69
+
70
+ BUNDLED WITH
71
+ 2.1.2
data/README.md ADDED
@@ -0,0 +1,88 @@
1
+ [![Vulnerabilities](https://snyk.io/test/github/gonace/obscured.heartbeat/badge.svg)](https://snyk.io/test/github/gonace/obscured.heartbeat)
2
+ [![Build Status](https://travis-ci.org/gonace/Obscured.Heartbeat.svg?branch=master)](https://travis-ci.org/gonace/Obscured.Heartbeat)
3
+ [![Test Coverage](https://codeclimate.com/github/gonace/Obscured.Heartbeat/badges/coverage.svg)](https://codeclimate.com/github/gonace/Obscured.Heartbeat)
4
+ [![Code Climate](https://codeclimate.com/github/gonace/Obscured.Heartbeat/badges/gpa.svg)](https://codeclimate.com/github/gonace/Obscured.Heartbeat)
5
+
6
+ # Obscured::Heartbeat
7
+ ## Introduction
8
+ Obscured Heartbeat adds heartbeat to a separate collection for an entity (Document), the naming of the class (Mongoid Document) is used for naming the heartbeat collection, so if the class is named "Host" the collection name will end up being "host_heartbeat".
9
+
10
+ ## Installation
11
+ ### Requirements
12
+ - activesupport
13
+ - mongoid
14
+ - mongoid_search
15
+
16
+ ##### Add this line to your application's Gemfile
17
+ ```ruby
18
+ gem 'obscured-heartbeat', :git => 'https://github.com/gonace/Obscured.Heartbeat.git', :branch => 'master'
19
+ ```
20
+
21
+ ##### Execute
22
+ ```
23
+ $ bundle
24
+ ```
25
+
26
+ ### Usage
27
+ #### Base
28
+ Use this in files where you create non-default log collections.
29
+ ```ruby
30
+ require 'obscured-heartbeat'
31
+ ```
32
+
33
+
34
+ ### Example
35
+ #### Document
36
+ ```ruby
37
+ require 'obscured-heartbeat'
38
+
39
+ module Obscured
40
+ class Host
41
+ include Mongoid::Document
42
+ include Mongoid::Timestamps
43
+ include Obscured::Heartbeat::Tracker
44
+
45
+ field :name, type: String
46
+ field :hostname, type: String
47
+ end
48
+ end
49
+
50
+
51
+ host = Obscured::Host.create(:name => "John Doe", :hostname => "domain.tld")
52
+ heartbeat = host.add_heartbeat(distribution: { name: 'Ubuntu', release: '19.04', codename: 'disco', description: 'Ubuntu 19.04' }, hostname: 'host.domain.tld', ip_address: '10.0.1.1', uptime: Time.now.to_i)
53
+
54
+ #returns array of heartbeats for document (proprietor)
55
+ host.get_heartbeat
56
+ host.heartbeats
57
+
58
+ #returns heartbeat by id
59
+ host.get_heartbeat(heartbeat.id.to_s)
60
+
61
+ #returns array of heartbeats by predefined params, supports pagination
62
+ host.find_heartbeats({ hostname: "domain.tld" }, { limit: 20, skip: 0, order: :created_at.desc, only: [:id, :distrubuton, :hostname, :ip_address, :uptime, :created_at, :updated_at, :proprietor] })
63
+
64
+ #retuns array of heartbeats
65
+ host.search_heartbeats("domain.tld", { limit: 20, skip: 0, order: :created_at.desc })
66
+ ```
67
+
68
+ #### Service
69
+ ```ruby
70
+ module Obscured
71
+ class HostHeartbeatService
72
+ include Mongoid::Timeline::Service::Base
73
+ end
74
+ end
75
+
76
+ module Obscured
77
+ class PackageSynchronizer
78
+ def initialize(host)
79
+ @host = host
80
+ @service = Obscured::HostHeartbeatService.new
81
+ end
82
+
83
+ def last_heartbeat
84
+ @host.by(proprietor: { host_id: host.id }).last
85
+ end
86
+ end
87
+ end
88
+ ```
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongoid'
4
+ require 'mongoid_search'
5
+
6
+ Mongoid::Search.setup do |cfg|
7
+ cfg.strip_symbols = /["]/
8
+ cfg.strip_accents = //
9
+ end
10
+
11
+ require 'obscured-heartbeat/record'
12
+ require 'obscured-heartbeat/service'
13
+ require 'obscured-heartbeat/tracker'
14
+
15
+ module Mongoid
16
+ module Heartbeat
17
+ end
18
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongoid'
4
+ require 'mongoid_search'
5
+
6
+ module Mongoid
7
+ module Heartbeat
8
+ module Record
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ include Mongoid::Document
13
+ include Mongoid::Search
14
+ include Mongoid::Timestamps
15
+
16
+ field :distribution, type: Hash
17
+ field :hostname, type: String
18
+ field :ip_address, type: String
19
+ field :uptime, type: Integer
20
+ field :proprietor, type: Hash
21
+
22
+ index({ hostname: 1 }, background: true)
23
+ index({ _keywords: 1 }, background: true)
24
+
25
+ search_in :id, :hostname, :ip_address, proprietor: %i[host_id gateway_id]
26
+ end
27
+
28
+ module ClassMethods
29
+ def make(params = {})
30
+ raise ArgumentError, 'distribution missing' if params[:distribution].blank?
31
+ raise ArgumentError, 'hostname missing' if params[:hostname].blank?
32
+ raise ArgumentError, 'ip_address missing' if params[:ip_address].blank?
33
+ raise ArgumentError, 'uptime missing' if params[:uptime].blank?
34
+ raise ArgumentError, 'proprietor missing' if params[:proprietor].blank?
35
+
36
+ doc = new
37
+ doc.distribution = params[:distribution]
38
+ doc.hostname = params[:hostname]
39
+ doc.ip_address = params[:ip_address]
40
+ doc.uptime = params[:uptime]
41
+ doc.proprietor = params[:proprietor]
42
+ doc
43
+ end
44
+
45
+ def make!(params = {})
46
+ doc = make(params)
47
+ doc.save!
48
+ doc
49
+ end
50
+
51
+ def by(params = {}, options = {})
52
+ limit = options[:limit].blank? ? nil : options[:limit].to_i
53
+ skip = options[:skip].blank? ? nil : options[:skip].to_i
54
+ order = options[:order].blank? ? :created_at.desc : options[:order]
55
+ only = options[:only].blank? ? %i[id distrubuton hostname ip_address uptime created_at updated_at proprietor] : options[:only]
56
+
57
+ query = {}
58
+ query[:hostname] = params[:hostname] if params[:hostname]
59
+ params[:proprietor]&.map { |k, v| query.merge!("proprietor.#{k}" => v) }
60
+
61
+ criterion = where(query).only(only).limit(limit).skip(skip)
62
+ criterion = criterion.order_by(order) if order
63
+
64
+ docs = criterion.to_a
65
+ docs
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ module Heartbeat
5
+ module Service
6
+ module Base
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ def all(criterion = {})
12
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
13
+ m.all(criterion).to_a
14
+ end
15
+ end
16
+
17
+ def find(*args)
18
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
19
+ m.find(*args)
20
+ end
21
+ end
22
+
23
+ def find_by(attrs = {})
24
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
25
+ m.find_by(attrs).to_a
26
+ end
27
+ end
28
+
29
+ def where(expression)
30
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
31
+ m.where(expression).to_a
32
+ end
33
+ end
34
+
35
+ def by(params = {}, options = {})
36
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
37
+ m.by(params, options)
38
+ end
39
+ end
40
+
41
+ def delete(id)
42
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
43
+ m.where(id: id.to_s).delete
44
+ end
45
+ end
46
+
47
+ class Record
48
+ include Mongoid::Heartbeat::Record
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/concern'
4
+
5
+ module Mongoid
6
+ module Heartbeat
7
+ module Tracker
8
+ extend ActiveSupport::Concern
9
+
10
+ class Record
11
+ include Mongoid::Heartbeat::Record
12
+ end
13
+
14
+ # Adds heartbeat to the x_heartbeat collection for document. This is
15
+ # only called on manually.
16
+ #
17
+ # @example Add heartbeat.
18
+ # document.add_heartbeat
19
+ #
20
+ # @return [ document ]
21
+ def add_heartbeat(event)
22
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
23
+ m.make!(event.merge(proprietor: { "#{self.class.name.demodulize.downcase}_id".to_sym => id }))
24
+ end
25
+ end
26
+
27
+ # Get an heartbeat from the x_heartbeat collection for document. This is
28
+ # only called on manually.
29
+ #
30
+ # @example Get heartbeat.
31
+ # document.get_heartbeat(id)
32
+ #
33
+ # @return [ document ]
34
+ def get_heartbeat(id)
35
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
36
+ m.find(id)
37
+ end
38
+ end
39
+
40
+ # Get heartbeats from the x_heartbeat collection for document by proprietor. This is
41
+ # only called on manually.
42
+ #
43
+ # @example Get heartbeats.
44
+ # document.get_heartbeats
45
+ # document.heartbeats
46
+ #
47
+ # @return [ documents ]
48
+ def get_heartbeats
49
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
50
+ m.by(proprietor: { "#{self.class.name.demodulize.downcase}_id".to_sym => id })
51
+ end
52
+ end
53
+ alias heartbeats get_heartbeats
54
+
55
+ # Find heartbeats from the x_heartbeat collection for document. This is
56
+ # only called on manually.
57
+ #
58
+ # @example Get heartbeats.
59
+ # document.find_heartbeats(params, options)
60
+ #
61
+ # @return [ documents ]
62
+ def find_heartbeats(params, options)
63
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
64
+ m.by({ proprietor: { "#{self.class.name.demodulize.downcase}_id".to_sym => id } }.merge(params), options)
65
+ end
66
+ end
67
+
68
+ # Search heartbeats from the x_heartbeat collection for document. This is
69
+ # only called on manually.
70
+ #
71
+ # @example Get heartbeats.
72
+ # document.search_heartbeats(text, options)
73
+ #
74
+ # @return [ documents ]
75
+ def search_heartbeats(text, options)
76
+ limit = options[:limit].blank? ? nil : options[:limit].to_i
77
+ skip = options[:skip].blank? ? nil : options[:skip].to_i
78
+ order = options[:order].blank? ? :created_at.desc : options[:order]
79
+
80
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
81
+ criteria = m.full_text_search(text)
82
+ criteria = criteria.order_by(order) if order
83
+ criteria = criteria.limit(limit).skip(skip)
84
+
85
+ docs = criteria.to_a
86
+ docs
87
+ end
88
+ end
89
+
90
+ # Edit an heartbeat from the x_heartbeat collection by id. This is
91
+ # only called on manually.
92
+ #
93
+ # @example Get heartbeat.
94
+ # document.edit_heartbeat(id, params)
95
+ #
96
+ # @return [ document ]
97
+ def edit_heartbeat(id, params = {})
98
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
99
+ hb = m.where(id: id).first
100
+ hb.hostname = params[:hostname] if params[:hostname]
101
+ hb.save
102
+ hb
103
+ end
104
+ end
105
+
106
+ # Delete an heartbeat from the x_heartbeat collection by id. This is
107
+ # only called on manually.
108
+ #
109
+ # @example Get heartbeat.
110
+ # document.delete_heartbeat(id)
111
+ #
112
+ # @return [ document ]
113
+ def delete_heartbeat(id)
114
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
115
+ m.where(id: id).delete
116
+ end
117
+ end
118
+
119
+ # Clear heartbeats from the x_heartbeat collection for document. This is
120
+ # only called on manually.
121
+ #
122
+ # @example Get heartbeats.
123
+ # document.clear_heartbeats
124
+ #
125
+ # @return [ documents ]
126
+ def clear_heartbeats
127
+ Record.with(collection: "#{self.class.name.demodulize.downcase}_heartbeat") do |m|
128
+ m.where(proprietor: { "#{self.class.name.demodulize.downcase}_id".to_sym => id }).delete
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ module Heartbeat
5
+ VERSION = '1.0.0'
6
+ end
7
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'obscured-heartbeat/version'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = 'obscured-heartbeat'
9
+ gem.version = Mongoid::Heartbeat::VERSION
10
+ gem.authors = ['Erik Hennerfors']
11
+ gem.email = ['erik.hennerfors@obscured.se']
12
+ gem.description = 'Default database heartbeat ability'
13
+ gem.summary = 'Default database heartbeat ability'
14
+ gem.homepage = 'https://github.com/gonace/Obscured.Heartbeat'
15
+
16
+ gem.required_ruby_version = '>= 2'
17
+
18
+ gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
19
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
20
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
21
+ gem.require_paths = ['lib']
22
+
23
+ gem.add_dependency 'activesupport'
24
+ gem.add_dependency 'mongoid'
25
+ gem.add_dependency 'mongoid_search'
26
+
27
+ gem.add_development_dependency 'factory_bot'
28
+ gem.add_development_dependency 'rspec'
29
+ gem.add_development_dependency 'simplecov'
30
+ end
@@ -0,0 +1,11 @@
1
+ spec:
2
+ options:
3
+ raise_not_found_error: false
4
+ clients:
5
+ default:
6
+ database: heartbeat_testing
7
+ hosts:
8
+ - localhost:27017
9
+ options:
10
+ max_pool_size: 100
11
+ min_pool_size: 5
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../helpers/gateway_document'
4
+
5
+ FactoryBot.define do
6
+ factory :gateway, class: Obscured::Gateway do
7
+ name { 'Gateway Sweden' }
8
+ hostname { 'gateway.domain.tld' }
9
+ end
10
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../lib/obscured-heartbeat/record'
4
+
5
+ FactoryBot.define do
6
+ factory :heartbeat, class: Mongoid::Heartbeat::Record do
7
+ distribution {
8
+ {
9
+ name: 'Ubuntu',
10
+ release: '19.04',
11
+ codename: 'disco',
12
+ description: 'Ubuntu 19.04'
13
+ }
14
+ }
15
+ hostname { 'host.domain.tld' }
16
+ ip_address { '10.0.1.1' }
17
+ uptime { 1561391862 }
18
+
19
+ trait :with_host do
20
+ proprietor { { host_id: BSON::ObjectId.new } }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../helpers/host_document'
4
+
5
+ FactoryBot.define do
6
+ factory :host, class: Obscured::Host do
7
+ name { 'host' }
8
+ hostname { 'hostname.domain.tld' }
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Obscured
4
+ class Gateway
5
+ include Mongoid::Document
6
+ include Mongoid::Timestamps
7
+ include Mongoid::Heartbeat::Tracker
8
+
9
+ store_in collection: 'gateways'
10
+
11
+ field :name, type: String
12
+ field :hostname, type: String
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Obscured
4
+ class Host
5
+ include Mongoid::Document
6
+ include Mongoid::Timestamps
7
+ include Mongoid::Heartbeat::Tracker
8
+
9
+ store_in collection: 'hosts'
10
+
11
+ field :name, type: String
12
+ field :hostname, type: String
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ module Heartbeat
5
+ module Service
6
+ class Host
7
+ include Mongoid::Heartbeat::Service::Base
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'setup'
4
+ require_relative 'helpers/host_document'
5
+ require_relative 'helpers/host_service'
6
+
7
+
8
+ describe Mongoid::Heartbeat::Service::Host do
9
+ let!(:host) { FactoryBot.create(:host) }
10
+ let!(:host2) { FactoryBot.create(:host, hostname: 'host2.domain.tld') }
11
+ let!(:service) { Mongoid::Heartbeat::Service::Host.new }
12
+ let!(:template) {
13
+ {
14
+ distribution: {
15
+ name: 'Ubuntu',
16
+ release: '19.04',
17
+ codename: 'disco',
18
+ description: 'Ubuntu 19.04'
19
+ },
20
+ hostname: 'host.domain.tld',
21
+ ip_address: '10.0.1.1',
22
+ uptime: Time.now.to_i
23
+ }
24
+ }
25
+
26
+ before(:each) do
27
+ 5.times do
28
+ host.add_heartbeat(template)
29
+ end
30
+
31
+ 3.times do
32
+ host2.add_heartbeat(template.merge(hostname: host2.hostname))
33
+ end
34
+ end
35
+
36
+ describe 'all' do
37
+ let(:response) { service.all }
38
+
39
+ it { expect(response.to_a.count).to eq(8) }
40
+ end
41
+
42
+ describe 'find' do
43
+ let!(:heartbeat) { host.add_heartbeat(template) }
44
+ let(:response) { service.find(heartbeat.id) }
45
+
46
+ it { expect(response).to_not be(nil) }
47
+ it { expect(response.id).to eq(heartbeat.id) }
48
+ end
49
+
50
+ describe 'find_by' do
51
+ let!(:heartbeat) { host.add_heartbeat(template) }
52
+ let(:response) { service.find_by(hostname: 'host.domain.tld') }
53
+
54
+ it { expect(response).to_not be(nil) }
55
+ it { expect(response.count).to eq(1) }
56
+ end
57
+
58
+ describe 'by' do
59
+ context 'proprietor' do
60
+ let(:response) { service.by(proprietor: { host_id: host.id }) }
61
+
62
+ it { expect(response.count).to eq(5) }
63
+ end
64
+ end
65
+
66
+ describe 'where' do
67
+ context 'returns correct documents' do
68
+ let(:response) { service.where(hostname: 'host2.domain.tld') }
69
+
70
+ it { expect(response.count).to eq(3) }
71
+ end
72
+ end
73
+
74
+ describe 'delete' do
75
+ context 'deletes document by id' do
76
+ let!(:heartbeat) { host.add_heartbeat(template) }
77
+
78
+ it { expect(service.delete(heartbeat.id)).to eq(1) }
79
+ end
80
+ end
81
+ end
data/spec/setup.rb ADDED
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Pull in test utilities
4
+ require 'factory_bot'
5
+ require 'pp'
6
+ require 'rspec'
7
+ require 'simplecov'
8
+
9
+ # pull in the code
10
+ require_relative '../lib/obscured-heartbeat'
11
+
12
+ Mongoid.load!(File.join(File.dirname(__FILE__), '/config/mongoid.yml'), 'spec')
13
+ Mongo::Logger.logger.level = Logger::ERROR
14
+
15
+ RSpec.configure do |c|
16
+ c.order = :random
17
+ c.filter_run :focus
18
+ c.run_all_when_everything_filtered = true
19
+
20
+ c.include FactoryBot::Syntax::Methods
21
+
22
+ c.before(:suite) do
23
+ FactoryBot.find_definitions
24
+ Mongoid.purge!
25
+
26
+ Mongoid::Search.setup do |cfg|
27
+ cfg.strip_symbols = /[\"]/
28
+ cfg.strip_accents = //
29
+ end
30
+ end
31
+
32
+ c.before(:each) do
33
+ Mongoid.purge!
34
+ end
35
+
36
+ c.after(:suite) do
37
+ Mongoid.purge!
38
+ end
39
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'setup'
4
+ require_relative 'helpers/host_document'
5
+ require_relative 'helpers/gateway_document'
6
+
7
+
8
+ describe Mongoid::Heartbeat::Tracker do
9
+ let(:host) { FactoryBot.create(:host) }
10
+ let(:gateway) { FactoryBot.create(:gateway) }
11
+ let!(:template) {
12
+ {
13
+ distribution: {
14
+ name: 'Ubuntu',
15
+ release: '19.04',
16
+ codename: 'disco',
17
+ description: 'Ubuntu 19.04'
18
+ },
19
+ hostname: 'host.domain.tld',
20
+ ip_address: '10.0.1.1',
21
+ uptime: Time.now.to_i
22
+ }
23
+ }
24
+
25
+ describe 'write heartbeat' do
26
+ context 'validates that that heartbeats is written to correct collection' do
27
+ let!(:host_heartbeat) { host.add_heartbeat(template) }
28
+ let!(:gateway_heartbeat) { gateway.add_heartbeat(template) }
29
+
30
+ context 'for host' do
31
+ it { expect(host_heartbeat.hostname).to eq(template[:hostname]) }
32
+ it { expect(host_heartbeat.proprietor).to eq(host_id: host.id) }
33
+
34
+ context 'get heartbeat' do
35
+ let!(:heartbeat) { host.add_heartbeat(template) }
36
+ let!(:response) { host.get_heartbeat(heartbeat.id) }
37
+
38
+ it { expect(response.hostname).to eq(template[:hostname]) }
39
+ it { expect(response.proprietor).to eq("host_id" => host.id) }
40
+ end
41
+
42
+ context 'get heartbeats' do
43
+ let!(:response) { host.get_heartbeats }
44
+
45
+ it { expect(response.length).to eq(1) }
46
+ end
47
+
48
+ context 'find heartbeats' do
49
+ let!(:heartbeat) { host.add_heartbeat(template) }
50
+ let!(:heartbeat) { host.add_heartbeat(template) }
51
+ let!(:heartbeat3) { host.add_heartbeat(template) }
52
+ let!(:response) { host.find_heartbeats({ hostname: template[:hostname] }, { }) }
53
+
54
+ it { expect(response.length).to eq(3) }
55
+ end
56
+
57
+ context 'search heartbeats' do
58
+ before(:each) do
59
+ 10.times do
60
+ host.add_heartbeat(template)
61
+ end
62
+ end
63
+
64
+ let!(:heartbeat) { host.add_heartbeat(template) }
65
+ let!(:heartbeat2) { host.add_heartbeat(template) }
66
+ let!(:response) { host.search_heartbeats(host.id, limit: 5) }
67
+
68
+ it { expect(response.length).to eq(5) }
69
+ end
70
+ end
71
+
72
+ context 'for gateway' do
73
+ it { expect(gateway_heartbeat.hostname).to eq(template[:hostname]) }
74
+ it { expect(gateway_heartbeat.proprietor).to eq(gateway_id: gateway.id) }
75
+
76
+ context 'get heartbeat' do
77
+ let!(:heartbeat) { gateway.add_heartbeat(template) }
78
+ let!(:response) { gateway.get_heartbeat(heartbeat.id) }
79
+
80
+ it { expect(response.id).to eq(heartbeat.id) }
81
+ it { expect(response.hostname).to eq(template[:hostname]) }
82
+ it { expect(response.proprietor).to eq("gateway_id" => gateway.id) }
83
+ end
84
+
85
+ context 'get heartbeats' do
86
+ let!(:response) { gateway.get_heartbeats }
87
+
88
+ it { expect(response.length).to eq(1) }
89
+ end
90
+
91
+ context 'find heartbeats' do
92
+ let!(:heartbeat) { gateway.add_heartbeat(template) }
93
+ let!(:heartbeat2) { gateway.add_heartbeat(template) }
94
+ let!(:heartbeat3) { gateway.add_heartbeat(template) }
95
+ let!(:response) { host.find_heartbeats({ hostname: template[:hostname] }, limit: 1) }
96
+
97
+ it { expect(response.length).to eq(1) }
98
+ end
99
+
100
+ context 'search heartbeats' do
101
+ before(:each) do
102
+ 10.times do
103
+ gateway.add_heartbeat(template)
104
+ end
105
+ end
106
+ let!(:response) { gateway.search_heartbeats(gateway.id, limit: 5) }
107
+
108
+ it { expect(response.length).to eq(5) }
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'setup'
4
+ require_relative 'helpers/host_document'
5
+
6
+
7
+ describe Mongoid::Heartbeat::Tracker do
8
+ let(:host) { FactoryBot.create(:host) }
9
+ let(:host2) { FactoryBot.create(:host, hostname: 'host2.domain.tld') }
10
+ let!(:template) {
11
+ {
12
+ distribution: {
13
+ name: 'Ubuntu',
14
+ release: '19.04',
15
+ codename: 'disco',
16
+ description: 'Ubuntu 19.04'
17
+ },
18
+ hostname: 'host.domain.tld',
19
+ ip_address: '10.0.1.1',
20
+ uptime: Time.now.to_i
21
+ }
22
+ }
23
+
24
+ describe 'heartbeat' do
25
+ context 'add heartbeat' do
26
+ let!(:heartbeat) { host.add_heartbeat(template) }
27
+
28
+ it { expect(heartbeat.hostname).to eq(template[:hostname]) }
29
+ it { expect(heartbeat.proprietor).to eq(host_id: host.id) }
30
+ end
31
+
32
+ context 'get heartbeat' do
33
+ let!(:heartbeat) { host.add_heartbeat(template) }
34
+ let(:response) { host.get_heartbeat(heartbeat.id) }
35
+
36
+ it { expect(response.id).to eq(heartbeat.id) }
37
+ it { expect(response.hostname).to eq(heartbeat.hostname) }
38
+ end
39
+
40
+ context 'get heartbeats' do
41
+ let!(:heartbeat) { host.add_heartbeat(template) }
42
+ let!(:heartbeat2) { host.add_heartbeat(template) }
43
+ let(:response) { host.get_heartbeats }
44
+
45
+ it { expect(response.count).to eq(2) }
46
+ end
47
+
48
+ context 'find heartbeats' do
49
+ let(:response) { host.find_heartbeats({ hostname: host.hostname }, {}) }
50
+
51
+ before(:each) do
52
+ host.add_heartbeat(template.merge(hostname: host.hostname))
53
+ host.add_heartbeat(template.merge(hostname: host.hostname))
54
+ host.add_heartbeat(template.merge(hostname: 'foo.bar.tld'))
55
+ end
56
+
57
+ it { expect(response.count).to eq(2) }
58
+ end
59
+
60
+ context 'search heartbeats' do
61
+ before(:each) do
62
+ 10.times do
63
+ host.add_heartbeat(template)
64
+ end
65
+
66
+ 5.times do
67
+ host2.add_heartbeat(template)
68
+ end
69
+ end
70
+
71
+ context 'via id with limit' do
72
+ let(:response) { host.search_heartbeats(host.id.to_s, limit: 5) }
73
+
74
+ it { expect(response.count).to eq(5) }
75
+ end
76
+
77
+ context 'via hostname with limit' do
78
+ let(:response) { host.search_heartbeats(template[:hostname], limit: 10) }
79
+
80
+ it { expect(response.length).to eq(10) }
81
+ end
82
+ end
83
+
84
+ context 'edit heartbeat' do
85
+ let!(:heartbeat) { host.add_heartbeat(template) }
86
+
87
+ context 'updates message for the event' do
88
+ before(:each) do
89
+ host.edit_heartbeat(heartbeat.id, hostname: 'host3.domain.tld')
90
+ end
91
+
92
+ it { expect(host.get_heartbeat(heartbeat.id).hostname).to eq('host3.domain.tld') }
93
+ end
94
+ end
95
+
96
+ context 'delete heartbeat' do
97
+ let!(:heartbeat) { host.add_heartbeat(template) }
98
+
99
+ context 'deletes the event' do
100
+ before(:each) do
101
+ host.delete_heartbeat(heartbeat.id)
102
+ end
103
+
104
+ it { expect(host.get_heartbeat(heartbeat.id)).to be_nil }
105
+ end
106
+ end
107
+
108
+ context 'clear heartbeats' do
109
+ before(:each) do
110
+ 10.times do
111
+ host.add_heartbeat(template)
112
+ end
113
+ end
114
+
115
+ it { expect(host.get_heartbeats.count).to be(10) }
116
+
117
+ context 'clear all event' do
118
+ before(:each) do
119
+ host.clear_heartbeats
120
+ end
121
+
122
+ it { expect(host.get_heartbeats.count).to be(0) }
123
+ end
124
+ end
125
+ end
126
+ end
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: obscured-heartbeat
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Erik Hennerfors
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-02-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mongoid
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mongoid_search
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: factory_bot
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Default database heartbeat ability
98
+ email:
99
+ - erik.hennerfors@obscured.se
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".codeclimate.yml"
105
+ - ".github/workflows/gem-push.yml"
106
+ - ".gitignore"
107
+ - ".rubocop.yml"
108
+ - ".ruby-gemset"
109
+ - ".ruby-version"
110
+ - ".simplecov"
111
+ - ".travis.yml"
112
+ - Gemfile
113
+ - Gemfile.lock
114
+ - README.md
115
+ - lib/obscured-heartbeat.rb
116
+ - lib/obscured-heartbeat/record.rb
117
+ - lib/obscured-heartbeat/service.rb
118
+ - lib/obscured-heartbeat/tracker.rb
119
+ - lib/obscured-heartbeat/version.rb
120
+ - obscured-heartbeat.gemspec
121
+ - spec/config/mongoid.yml
122
+ - spec/factories/gateway_factory.rb
123
+ - spec/factories/heartbeat_factory.rb
124
+ - spec/factories/host_factory.rb
125
+ - spec/helpers/gateway_document.rb
126
+ - spec/helpers/host_document.rb
127
+ - spec/helpers/host_service.rb
128
+ - spec/host_service_spec.rb
129
+ - spec/setup.rb
130
+ - spec/tracker_multiple_spec.rb
131
+ - spec/tracker_single_spec.rb
132
+ homepage: https://github.com/gonace/Obscured.Heartbeat
133
+ licenses: []
134
+ metadata: {}
135
+ post_install_message:
136
+ rdoc_options: []
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '2'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ requirements: []
150
+ rubygems_version: 3.0.3
151
+ signing_key:
152
+ specification_version: 4
153
+ summary: Default database heartbeat ability
154
+ test_files:
155
+ - spec/config/mongoid.yml
156
+ - spec/factories/gateway_factory.rb
157
+ - spec/factories/heartbeat_factory.rb
158
+ - spec/factories/host_factory.rb
159
+ - spec/helpers/gateway_document.rb
160
+ - spec/helpers/host_document.rb
161
+ - spec/helpers/host_service.rb
162
+ - spec/host_service_spec.rb
163
+ - spec/setup.rb
164
+ - spec/tracker_multiple_spec.rb
165
+ - spec/tracker_single_spec.rb