w-stdlib 0.0.1
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 +7 -0
- data/Gemfile +10 -0
- data/lib/aws.rb +84 -0
- data/lib/case_insensitive_hash.rb +24 -0
- data/lib/core_ext/array.rb +57 -0
- data/lib/core_ext/aws.rb +38 -0
- data/lib/core_ext/file.rb +19 -0
- data/lib/core_ext/hash.rb +27 -0
- data/lib/core_ext/io.rb +20 -0
- data/lib/core_ext/ipv4net.rb +9 -0
- data/lib/core_ext/object.rb +16 -0
- data/lib/core_ext/openssl.rb +38 -0
- data/lib/core_ext/string.rb +110 -0
- data/lib/core_ext/uri.rb +21 -0
- data/lib/github_client.rb +59 -0
- data/lib/glob.rb +13 -0
- data/lib/prelude.rb +25 -0
- data/lib/processes.rb +74 -0
- data/lib/uri.rb +16 -0
- data/lib/w-stdlib.rb +1 -0
- data/w-stdlib.gemspec +9 -0
- metadata +65 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f7cb8e2bf20665a3a90bfa7cdfbf7db465f5867bce893d78783b3ccfa38d245a
|
4
|
+
data.tar.gz: 3ce32ae202b1a5f77fa3cf90e97295d775a4c2fa6487daa92fbb8a4f6c6830fa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 43bae6362746dd9b6bbddf3fa1fc74a8272be4db2e15df2fb65daaa9905a7938b2a8f5faf45228e29348678bd2d390a3258eedae83218ff37ee68e1c5a4ed4b5
|
7
|
+
data.tar.gz: 7e8447678675d9df0e2c8fea625833c893a471403df9713aac377b06a86afbfbe34d2697e86b237e860708b2bd96073528fe427d8ff31b1311a42bf1c323873f
|
data/Gemfile
ADDED
data/lib/aws.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative '../lib/glob'
|
2
|
+
require_relative '../lib/core_ext/string'
|
3
|
+
require_relative '../lib/core_ext/object'
|
4
|
+
require_relative '../lib/core_ext/hash'
|
5
|
+
|
6
|
+
using StringExt
|
7
|
+
using ObjectExt
|
8
|
+
using HashExt
|
9
|
+
|
10
|
+
|
11
|
+
module IAM
|
12
|
+
class AssumeRoleStatement
|
13
|
+
def initialize(s)
|
14
|
+
@effect = s['Effect']
|
15
|
+
@action = s['Action']
|
16
|
+
@principal = s['Principal'].map_vals(&:lift_array) # principals can be string or string[]
|
17
|
+
end
|
18
|
+
|
19
|
+
def allow?
|
20
|
+
@effect.downcase == 'allow'
|
21
|
+
end
|
22
|
+
|
23
|
+
def deny?
|
24
|
+
@effect.downcase == 'deny'
|
25
|
+
end
|
26
|
+
|
27
|
+
def assume_role?
|
28
|
+
@action.include? 'sts:AssumeRole'
|
29
|
+
end
|
30
|
+
|
31
|
+
def applies_to_principal?(arn)
|
32
|
+
@principal.fetch('AWS', []).any? { Glob.new(_1).match? arn }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class AssumeRolePolicyDocument
|
37
|
+
def initialize(doc)
|
38
|
+
@doc = doc
|
39
|
+
@statements = doc['Statement'].map { AssumeRoleStatement.new _1 }
|
40
|
+
end
|
41
|
+
|
42
|
+
# initializes from a hash of params. it supports docs as
|
43
|
+
# url encoded json strings, like the aws api returns or
|
44
|
+
# docs that are nested hashes and arrays
|
45
|
+
def self.from_role(role)
|
46
|
+
doc = role[:assume_role_policy_document]
|
47
|
+
doc = role["AssumeRolePolicyDocument"] unless doc
|
48
|
+
raise 'invalid role' unless doc
|
49
|
+
|
50
|
+
doc = doc.url_decode.from_json if doc.is_a? String
|
51
|
+
|
52
|
+
self.new doc
|
53
|
+
end
|
54
|
+
|
55
|
+
def can_assume?(arn)
|
56
|
+
return false if explicitly_denied? arn
|
57
|
+
return true if explicitly_allowed? arn
|
58
|
+
false
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def explicitly_denied?(arn)
|
63
|
+
@statements.any? { _1.deny? && _1.assume_role? && _1.applies_to_principal?(arn) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def explicitly_allowed?(arn)
|
67
|
+
@statements.any? { _1.allow? && _1.assume_role? && _1.applies_to_principal?(arn) }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Role
|
72
|
+
attr_reader :doc, :arn
|
73
|
+
def initialize(params)
|
74
|
+
@params = params
|
75
|
+
@arn = params[:arn]
|
76
|
+
@arn = params['Arn'] unless @arn
|
77
|
+
@doc = AssumeRolePolicyDocument.from_role params
|
78
|
+
end
|
79
|
+
|
80
|
+
def can_assume?(arn)
|
81
|
+
@doc.can_assume?(arn)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class CaseInsensitiveHash < Hash
|
2
|
+
def [](key)
|
3
|
+
super _insensitive(key)
|
4
|
+
end
|
5
|
+
|
6
|
+
def []=(key, value)
|
7
|
+
super _insensitive(key), value
|
8
|
+
end
|
9
|
+
|
10
|
+
# Keeping it DRY.
|
11
|
+
protected
|
12
|
+
|
13
|
+
def _insensitive(key)
|
14
|
+
key.respond_to?(:upcase) ? key.upcase : key
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.from_pairs(pairs)
|
18
|
+
h = CaseInsensitiveHash.new
|
19
|
+
pairs.each do |k, v|
|
20
|
+
h[k] = v
|
21
|
+
end
|
22
|
+
h
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'parallel'
|
2
|
+
require 'etc'
|
3
|
+
require_relative '../../lib/core_ext/string'
|
4
|
+
|
5
|
+
using StringExt
|
6
|
+
|
7
|
+
module ArrayExt
|
8
|
+
refine Array do
|
9
|
+
def tail
|
10
|
+
self[1..self.length]
|
11
|
+
end
|
12
|
+
|
13
|
+
def but_last
|
14
|
+
self.tap(&:pop)
|
15
|
+
end
|
16
|
+
|
17
|
+
def choose
|
18
|
+
return first if length < 2
|
19
|
+
loop do
|
20
|
+
each_with_index { puts "#{_2 + 1}: #{block_given? ? yield(_1) : _1 }" }
|
21
|
+
print "> "
|
22
|
+
input = STDIN.gets.strip
|
23
|
+
break if input.downcase == 'q'
|
24
|
+
|
25
|
+
i = input.to_i
|
26
|
+
next if i <= 0 || i > length
|
27
|
+
|
28
|
+
return self[i - 1]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def p_each(opts=nil, &blk)
|
33
|
+
opts = {in_threads: Etc.nprocessors} if opts.nil?
|
34
|
+
Parallel.each(self, opts, &blk)
|
35
|
+
end
|
36
|
+
|
37
|
+
def p_map(opts=nil, &blk)
|
38
|
+
opts = {in_threads: Etc.nprocessors} if opts.nil?
|
39
|
+
Parallel.map(self, opts, &blk)
|
40
|
+
end
|
41
|
+
|
42
|
+
def puts_all
|
43
|
+
each { puts _1.to_s }
|
44
|
+
end
|
45
|
+
|
46
|
+
def search(str)
|
47
|
+
select do
|
48
|
+
s = block_given? ? yield(_1) : _1.to_s
|
49
|
+
s.matches_pat? str
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_h_by
|
54
|
+
map { [yield(_1), _1] }.to_h
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/core_ext/aws.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative './string'
|
2
|
+
require 'aws-sdk-iam'
|
3
|
+
require 'aws-sdk-core/arn_parser'
|
4
|
+
|
5
|
+
using StringExt
|
6
|
+
|
7
|
+
module IamExt
|
8
|
+
refine Aws::IAM::Client do
|
9
|
+
def arn_to_policies(arn)
|
10
|
+
arn = arn.strip
|
11
|
+
type, name = Aws::ARNParser.parse(arn).resource.split('/', 2) rescue return []
|
12
|
+
return [] unless name && type
|
13
|
+
|
14
|
+
policies = []
|
15
|
+
|
16
|
+
attached_policies = send(:"list_attached_#{type}_policies", {:"#{type}_name" => name}).attached_policies
|
17
|
+
attached_policies.each do |p|
|
18
|
+
error "fetching #{p.policy_arn}"
|
19
|
+
version_id = list_policy_versions(policy_arn: p.policy_arn).versions.find { _1.is_default_version }.version_id
|
20
|
+
policy = get_policy_version(policy_arn: p.policy_arn, version_id: version_id).policy_version
|
21
|
+
policies << policy.document.url_decode.from_json
|
22
|
+
rescue Aws::IAM::Errors::NoSuchEntity
|
23
|
+
error "#{a} #{p.policy_name} not found"
|
24
|
+
end
|
25
|
+
|
26
|
+
inline_policies = send(:"list_#{type}_policies", {:"#{type}_name" => name}).policy_names
|
27
|
+
inline_policies.each do |policy_name|
|
28
|
+
error "fetching #{policy_name}"
|
29
|
+
policy = send(:"get_#{type}_policy", {:"#{type}_name" => name, :policy_name => policy_name})
|
30
|
+
policies << policy.policy_document.url_decode.from_json
|
31
|
+
rescue Aws::IAM::Errors::NoSuchEntity
|
32
|
+
error "#{a} #{p.policy_arn} not found"
|
33
|
+
end
|
34
|
+
|
35
|
+
policies
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative '../../lib/core_ext/string'
|
2
|
+
|
3
|
+
using StringExt
|
4
|
+
|
5
|
+
module HashExt
|
6
|
+
refine Hash do
|
7
|
+
def map_vals
|
8
|
+
map { [_1, yield(_2)] }.to_h
|
9
|
+
end
|
10
|
+
|
11
|
+
def map_keys
|
12
|
+
map { [yield(_1), _2] }.to_h
|
13
|
+
end
|
14
|
+
|
15
|
+
def search(pat)
|
16
|
+
select { _1.to_s.matches_pat?(pat) || _2.to_s.matches_pat?(pat) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def search_keys(pat)
|
20
|
+
select { _1.to_s.matches_pat?(pat) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def puts_all
|
24
|
+
each { puts "#{_1}: #{_2}"}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/core_ext/io.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative './string'
|
2
|
+
|
3
|
+
using StringExt
|
4
|
+
|
5
|
+
module IOExt
|
6
|
+
refine IO do
|
7
|
+
def lines
|
8
|
+
read.lines.map(&:strip)
|
9
|
+
end
|
10
|
+
|
11
|
+
def json_props_or_lines(*path)
|
12
|
+
s = read
|
13
|
+
begin
|
14
|
+
s.from_json.lift_array.map { _1.dig(*path) }
|
15
|
+
rescue JSON::ParserError
|
16
|
+
s.lines
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require_relative '../case_insensitive_hash'
|
3
|
+
|
4
|
+
module OpenSSLExt
|
5
|
+
refine OpenSSL::X509::Certificate do
|
6
|
+
def cn
|
7
|
+
subject['CN']
|
8
|
+
end
|
9
|
+
|
10
|
+
def sans
|
11
|
+
extensions
|
12
|
+
.find { _1.oid == 'subjectAltName' }
|
13
|
+
.value
|
14
|
+
.split(/,\s+/)
|
15
|
+
.map { _1.gsub(/^DNS:/,'') }
|
16
|
+
end
|
17
|
+
|
18
|
+
def dns_names
|
19
|
+
[cn] + sans
|
20
|
+
end
|
21
|
+
end
|
22
|
+
refine OpenSSL::X509::Name do
|
23
|
+
def to_h
|
24
|
+
str = to_s
|
25
|
+
if str.start_with?("/")
|
26
|
+
# /A=B/C=D format
|
27
|
+
CaseInsensitiveHash.from_pairs str[1..-1].split("/").map { _1.split('=', 2) }
|
28
|
+
else
|
29
|
+
# Comma-separated
|
30
|
+
CaseInsensitiveHash.from_pairs str.split(",").map { _1.split('=', 2) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def [](key)
|
35
|
+
to_h[key]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'json'
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
module StringExt
|
6
|
+
refine String do
|
7
|
+
def from_json
|
8
|
+
JSON.parse self
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_b64
|
12
|
+
Base64.encode64 self
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_bool
|
16
|
+
self.downcase == 'true'
|
17
|
+
end
|
18
|
+
|
19
|
+
def from_b64
|
20
|
+
Base64.decode64 self
|
21
|
+
end
|
22
|
+
|
23
|
+
def url_encode
|
24
|
+
CGI.escape self
|
25
|
+
end
|
26
|
+
|
27
|
+
def url_decode
|
28
|
+
CGI.unescape self
|
29
|
+
end
|
30
|
+
|
31
|
+
def words
|
32
|
+
self.split(/\s+/)
|
33
|
+
end
|
34
|
+
|
35
|
+
def chars
|
36
|
+
self.split('')
|
37
|
+
end
|
38
|
+
|
39
|
+
def map(&blk)
|
40
|
+
self.chars.map(&blk).join('')
|
41
|
+
end
|
42
|
+
|
43
|
+
def select(&blk)
|
44
|
+
self.chars.select(&blk).join('')
|
45
|
+
end
|
46
|
+
|
47
|
+
def reject(&blk)
|
48
|
+
self.chars.reject(&blk).join('')
|
49
|
+
end
|
50
|
+
|
51
|
+
def any?(&blk)
|
52
|
+
self.chars.any?(&blk)
|
53
|
+
end
|
54
|
+
|
55
|
+
def all?(&blk)
|
56
|
+
self.chars.all?(&blk)
|
57
|
+
end
|
58
|
+
|
59
|
+
def grep(pat)
|
60
|
+
self.lines.select { _1.matches_pat? pat }
|
61
|
+
end
|
62
|
+
|
63
|
+
def matches_pat?(pat)
|
64
|
+
case pat
|
65
|
+
when String
|
66
|
+
self.include_ignore_case? pat
|
67
|
+
when Regexp
|
68
|
+
self =~ pat
|
69
|
+
else
|
70
|
+
raise "matches_pat? only works on String and Regexp. You passed: #{pat.class}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def prefix(p)
|
75
|
+
p + self
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_bs
|
79
|
+
n, units = self.scan(/([0-9.]+)(B|KB|MB|GB)/).first
|
80
|
+
raise "Invalid size: #{self}" unless n && units
|
81
|
+
sizes = {
|
82
|
+
'B' => 1,
|
83
|
+
'KB' => 1024,
|
84
|
+
'MB' => 1024 ** 2,
|
85
|
+
'GB' => 1024 ** 3,
|
86
|
+
}
|
87
|
+
scale = sizes.fetch(units, 1)
|
88
|
+
n.to_f*scale
|
89
|
+
end
|
90
|
+
|
91
|
+
def to_regexp
|
92
|
+
Regexp.new self
|
93
|
+
end
|
94
|
+
|
95
|
+
def regexp_encode
|
96
|
+
Regexp.quote self
|
97
|
+
end
|
98
|
+
|
99
|
+
def include_ignore_case?(s)
|
100
|
+
downcase.include? s.downcase
|
101
|
+
end
|
102
|
+
|
103
|
+
def is_numeric?
|
104
|
+
Float(self)
|
105
|
+
true
|
106
|
+
rescue
|
107
|
+
false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/lib/core_ext/uri.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module QueryParamsMixin
|
4
|
+
def query_params
|
5
|
+
query.nil? ? {} : URI.decode_www_form(query).to_h
|
6
|
+
end
|
7
|
+
|
8
|
+
def with_query_params
|
9
|
+
params = query_params
|
10
|
+
yield params
|
11
|
+
self.query = URI.encode_www_form(params)
|
12
|
+
self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module URI
|
17
|
+
class Generic
|
18
|
+
include QueryParamsMixin
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'http'
|
2
|
+
require 'json'
|
3
|
+
require 'uri'
|
4
|
+
require_relative '../lib/core_ext/uri'
|
5
|
+
require_relative '../lib/uri'
|
6
|
+
require_relative '../lib/core_ext/string'
|
7
|
+
|
8
|
+
using StringExt
|
9
|
+
|
10
|
+
class GithubClient
|
11
|
+
def initialize(username='', base_url='https://api.github.com')
|
12
|
+
@url = URI.parse base_url
|
13
|
+
@username = username
|
14
|
+
end
|
15
|
+
|
16
|
+
def repos
|
17
|
+
paginate('/repositories')
|
18
|
+
end
|
19
|
+
|
20
|
+
def repos_for_org(org)
|
21
|
+
paginate("/orgs/#{org}/repos")
|
22
|
+
end
|
23
|
+
|
24
|
+
def users
|
25
|
+
paginate('/users')
|
26
|
+
end
|
27
|
+
|
28
|
+
def user_perms(owner, repo, username)
|
29
|
+
url = @url.clone
|
30
|
+
url.path = "/repos/#{owner}/#{repo}/collaborators/#{username}/permission"
|
31
|
+
auth = {user: @username, pass: token}
|
32
|
+
puts url.to_s
|
33
|
+
HTTP.basic_auth(auth)
|
34
|
+
.headers({"Accept" => "application/vnd.github.v3+json"})
|
35
|
+
.get(url.to_s)
|
36
|
+
.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def token
|
41
|
+
File.read(File.join(ENV['HOME'], '.keys', 'github')).strip
|
42
|
+
end
|
43
|
+
def paginate(path)
|
44
|
+
url = @url.clone
|
45
|
+
url.path = path
|
46
|
+
Enumerator.new do |e|
|
47
|
+
paged_uri = URI::Paged.new(url)
|
48
|
+
loop do
|
49
|
+
repos = HTTP.get(paged_uri.get).to_s.from_json
|
50
|
+
break if repos.empty?
|
51
|
+
|
52
|
+
repos.each { e.yield _1 }
|
53
|
+
rescue JSON::ParserError
|
54
|
+
break
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
data/lib/glob.rb
ADDED
data/lib/prelude.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
def fatal(msg, code=1, pref='[!] ')
|
2
|
+
STDERR.puts pref + msg
|
3
|
+
exit code
|
4
|
+
end
|
5
|
+
|
6
|
+
def info(msg, pref='[+] ')
|
7
|
+
STDERR.puts pref + msg
|
8
|
+
end
|
9
|
+
|
10
|
+
def error(msg, pref='[!] ')
|
11
|
+
STDERR.puts pref + msg
|
12
|
+
end
|
13
|
+
|
14
|
+
def json_file(name)
|
15
|
+
JSON.parse File.read(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def home_join(*paths)
|
19
|
+
home = ENV['HOME']
|
20
|
+
if paths.empty?
|
21
|
+
home
|
22
|
+
else
|
23
|
+
File.join home, *paths
|
24
|
+
end
|
25
|
+
end
|
data/lib/processes.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'sys/proctable'
|
2
|
+
require_relative '../lib/core_ext/file'
|
3
|
+
require_relative '../lib/core_ext/string'
|
4
|
+
using FileExt
|
5
|
+
using StringExt
|
6
|
+
|
7
|
+
module Processes
|
8
|
+
def self.snapshot
|
9
|
+
Snapshot.new Sys::ProcTable.ps
|
10
|
+
end
|
11
|
+
|
12
|
+
class Snapshot
|
13
|
+
def initialize(procs)
|
14
|
+
@procs = procs
|
15
|
+
@pid_to_proc = @procs.map { [_1.pid, _1] }.to_h
|
16
|
+
end
|
17
|
+
|
18
|
+
def all
|
19
|
+
@procs.map { Processes::Process.new self, _1 }
|
20
|
+
end
|
21
|
+
|
22
|
+
def for_pid(pid)
|
23
|
+
proc = @pid_to_proc[pid]
|
24
|
+
return nil unless proc
|
25
|
+
Processes::Process.new self, proc
|
26
|
+
end
|
27
|
+
|
28
|
+
def search_cmdline(name)
|
29
|
+
@procs
|
30
|
+
.select { _1.cmdline.downcase.include? name.downcase }
|
31
|
+
.reject { _1.pid == ::Process.pid }
|
32
|
+
.map { Processes::Process.new self, _1 }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Process
|
37
|
+
def initialize(snapshot, proc)
|
38
|
+
raise 'proc cant be nil' unless proc
|
39
|
+
@snapshot = snapshot
|
40
|
+
@proc = proc
|
41
|
+
end
|
42
|
+
|
43
|
+
def parent
|
44
|
+
proc = @snapshot.for_pid(self.ppid)
|
45
|
+
return nil unless proc
|
46
|
+
Processes::Process.new @snapshot, proc
|
47
|
+
end
|
48
|
+
|
49
|
+
def open_files
|
50
|
+
raise unless pid.is_numeric?
|
51
|
+
`lsof -p #{pid}`
|
52
|
+
.lines
|
53
|
+
.drop(1)
|
54
|
+
.map { _1.strip.scan(/(\/.*$)/).first&.first }
|
55
|
+
.reject(&:nil?)
|
56
|
+
.uniq
|
57
|
+
.select { File.file? _1 }
|
58
|
+
.map { File.new _1 }
|
59
|
+
end
|
60
|
+
|
61
|
+
def sig_kill
|
62
|
+
raise unless pid.is_numeric?
|
63
|
+
`kill -9 #{pid}`
|
64
|
+
end
|
65
|
+
|
66
|
+
def children
|
67
|
+
@snapshot.all.select { _1.ppid == pid }.map { Process.new @snapshot, _1 }
|
68
|
+
end
|
69
|
+
|
70
|
+
private def method_missing(symbol, *args)
|
71
|
+
@proc.send symbol, *args
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/uri.rb
ADDED
data/lib/w-stdlib.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require ''
|
data/w-stdlib.gemspec
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
Gem::Specification.new do |g|
|
2
|
+
g.name = 'w-stdlib'
|
3
|
+
g.version = '0.0.1'
|
4
|
+
g.summary = 'Pre-alpha package that contains abstractions that I find useful when scripting. Not suitable for production use. Breaking changes highly likely even with minor version bumps. Use at your own risk'
|
5
|
+
g.description = g.summary
|
6
|
+
g.authors = ['will@btlr.dev']
|
7
|
+
g.email = 'will@btlr.dev'
|
8
|
+
g.files = Dir['lib/**/*'] + %w(Gemfile w-stdlib.gemspec)
|
9
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: w-stdlib
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- will@btlr.dev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-10-27 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Pre-alpha package that contains abstractions that I find useful when
|
14
|
+
scripting. Not suitable for production use. Breaking changes highly likely even
|
15
|
+
with minor version bumps. Use at your own risk
|
16
|
+
email: will@btlr.dev
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- Gemfile
|
22
|
+
- lib/aws.rb
|
23
|
+
- lib/case_insensitive_hash.rb
|
24
|
+
- lib/core_ext/array.rb
|
25
|
+
- lib/core_ext/aws.rb
|
26
|
+
- lib/core_ext/file.rb
|
27
|
+
- lib/core_ext/hash.rb
|
28
|
+
- lib/core_ext/io.rb
|
29
|
+
- lib/core_ext/ipv4net.rb
|
30
|
+
- lib/core_ext/object.rb
|
31
|
+
- lib/core_ext/openssl.rb
|
32
|
+
- lib/core_ext/string.rb
|
33
|
+
- lib/core_ext/uri.rb
|
34
|
+
- lib/github_client.rb
|
35
|
+
- lib/glob.rb
|
36
|
+
- lib/prelude.rb
|
37
|
+
- lib/processes.rb
|
38
|
+
- lib/uri.rb
|
39
|
+
- lib/w-stdlib.rb
|
40
|
+
- w-stdlib.gemspec
|
41
|
+
homepage:
|
42
|
+
licenses: []
|
43
|
+
metadata: {}
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
requirements: []
|
59
|
+
rubygems_version: 3.0.3
|
60
|
+
signing_key:
|
61
|
+
specification_version: 4
|
62
|
+
summary: Pre-alpha package that contains abstractions that I find useful when scripting.
|
63
|
+
Not suitable for production use. Breaking changes highly likely even with minor
|
64
|
+
version bumps. Use at your own risk
|
65
|
+
test_files: []
|