chef_locker 0.1.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
+ SHA1:
3
+ metadata.gz: 4bee107a6d01f445def880bd797b5587ef0fd203
4
+ data.tar.gz: 176bf3f2e14b25b9abcc0b7d1a84657855786847
5
+ SHA512:
6
+ metadata.gz: '0279aeeb21600beb2cb7d6c54de3cdc117abf921b72a31a23fa6e315428ea495d55ed7342f5f5d6c0d12e14b764c0498de6ba8f26ddbfc180570e8654936d3bf'
7
+ data.tar.gz: d2cb5e6dd08d4278adefec17c28d59be4bff51c8c6b68216f43975797964fffa3e8b071809c832f87d1fa75bd19f72074583edb35a95e92f146f6c1d1269b6cb
data/.gitignore ADDED
@@ -0,0 +1,50 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ Gemfile.lock
46
+ .ruby-version
47
+ .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 AnyPerk Engineering
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # chef_locker
2
+
3
+ chef_locker is a Ruby gem that contains a script to prevent Chef clients from
4
+ converging.
5
+
6
+ To install, declare something like the following in Chef:
7
+ ```ruby
8
+ chef_gem 'chef_locker'
9
+ ```
10
+
11
+ To run the script, try something like the following in a screen/tmux session:
12
+ ```bash
13
+ $ sudo /opt/chefdk/embedded/bin/chef_locker 'Testing CDN host change'
14
+ ```
15
+ Wait until `Lock acquired` appears.
16
+
17
+ Note that if something like rvm is installed, you may have to create a wrapper
18
+ script to unset some Ruby-related environment variables.
data/bin/chef_locker ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ usage_string = "Usage: #{$0} MESSAGE"
4
+
5
+ if %w(-h --help).include?(ARGV[0])
6
+ puts usage_string
7
+ exit
8
+ end
9
+
10
+ require 'chef_locker'
11
+
12
+ begin
13
+ ChefLocker.new.lock(ARGV.join(' '))
14
+ rescue ArgumentError
15
+ abort usage_string
16
+ end
@@ -0,0 +1,18 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'chef_locker'
3
+ s.version = '0.1.0'
4
+ s.authors = ['AnyPerk Engineering']
5
+ s.email = ['engineering@anyperk.com']
6
+ s.summary = 'Lock Chef runs'
7
+ s.description = 'This contains a script to lock Chef runs.'
8
+ s.homepage = 'https://github.com/anyperk/chef_locker'
9
+ s.license = 'MIT'
10
+
11
+ s.add_dependency 'chef', '~> 12.0'
12
+ s.add_development_dependency 'rspec', '~> 3.5'
13
+
14
+ s.executables = %w(chef_locker)
15
+
16
+ s.files = `git ls-files`.split($/)
17
+ s.test_files = s.files.grep(%r{\Aspec/})
18
+ end
@@ -0,0 +1,31 @@
1
+ require 'chef'
2
+
3
+ # @see #lock
4
+ class ChefLocker
5
+ # @param output [#puts] IO-like object to output info to
6
+ def initialize(output: $stdout)
7
+ @output = output
8
+ @runlock = Chef::RunLock.new(Chef::Config.lockfile)
9
+ end
10
+
11
+ # Locks Chef runs (prevents Chef clients from converging)
12
+ #
13
+ # @param message [#to_s] message to include in lock file
14
+ def lock(message)
15
+ message = message.to_s
16
+ raise ArgumentError, "Message can't be blank" if message.strip.empty?
17
+
18
+ @runlock.acquire
19
+ begin
20
+ @output.puts 'Lock acquired'
21
+ @runlock.save_pid
22
+ @runlock.runlock.write(' ' + message)
23
+ @runlock.runlock.fsync
24
+
25
+ # Now we block until interrupted (there might be a better way to do this)
26
+ loop { $stdin.read }
27
+ ensure
28
+ @runlock.release
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,65 @@
1
+ require 'fileutils'
2
+ require 'securerandom'
3
+
4
+ require 'chef_locker'
5
+
6
+ RSpec.describe ChefLocker do
7
+ let(:output) { StringIO.new }
8
+ subject(:locker) { ChefLocker.new(output: output) }
9
+
10
+ describe '#lock' do
11
+ context 'when the given message is empty' do
12
+ it 'raises ArgumentError' do
13
+ expect { locker.lock }.to raise_error(ArgumentError)
14
+ end
15
+ end
16
+
17
+ context 'when the given message is not blank' do
18
+ let(:lockfile) { "spec/lockfiles/#{SecureRandom.hex}.pid" }
19
+
20
+ before do
21
+ allow(Chef::Config).to receive(:lockfile).and_return(lockfile)
22
+ allow(locker).to receive(:loop)
23
+ end
24
+
25
+ after do
26
+ FileUtils.rm_f(lockfile)
27
+ end
28
+
29
+ it 'acquires the lock' do
30
+ reached = false
31
+ allow(locker).to receive(:loop) do
32
+ File.open(lockfile, 'r') do |f|
33
+ expect(f.flock(File::LOCK_NB | File::LOCK_EX)).to eq(false)
34
+ reached = true
35
+ end
36
+ end
37
+
38
+ locker.lock('test')
39
+ expect(reached).to eq(true)
40
+ end
41
+
42
+ it 'saves the PID and message in the lock file' do
43
+ message = SecureRandom.hex
44
+ locker.lock(message)
45
+
46
+ expect(IO.read(lockfile)).to eq("#{$$} #{message}")
47
+ end
48
+
49
+ it 'blocks' do
50
+ allow(locker).to receive(:loop).and_yield
51
+ expect($stdin).to receive(:read)
52
+
53
+ locker.lock('test')
54
+ end
55
+
56
+ it 'releases the lock' do
57
+ locker.lock('test')
58
+
59
+ File.open(lockfile, 'r') do |f|
60
+ expect(f.flock(File::LOCK_NB | File::LOCK_EX)).to eq(0)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
File without changes
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chef_locker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - AnyPerk Engineering
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: chef
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '12.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '12.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.5'
41
+ description: This contains a script to lock Chef runs.
42
+ email:
43
+ - engineering@anyperk.com
44
+ executables:
45
+ - chef_locker
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - Gemfile
51
+ - LICENSE
52
+ - README.md
53
+ - bin/chef_locker
54
+ - chef_locker.gemspec
55
+ - lib/chef_locker.rb
56
+ - spec/chef_locker_spec.rb
57
+ - spec/lockfiles/.gitkeep
58
+ homepage: https://github.com/anyperk/chef_locker
59
+ licenses:
60
+ - MIT
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 2.5.2
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: Lock Chef runs
82
+ test_files:
83
+ - spec/chef_locker_spec.rb
84
+ - spec/lockfiles/.gitkeep