knife-tagbulk 0.1.1 → 0.1.2
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 +8 -8
- data/README.md +9 -1
- data/VERSION +1 -1
- data/lib/chef/knife/tag_bulk_create.rb +49 -22
- data/lib/chef/knife/tag_bulk_delete.rb +91 -25
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MjllMjZlZmMzZDE4MzAzOTQwYmI0MTRkNDc2YWZmM2Q5NGI1MmI5ZQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NGE3MjFhNDJhNmI2YjY1YTdiODQwMzU3YTYzMzkwNjRiOWJhMzRkZg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MWQ5NzkwYjBlMDNjZmFhOGM3MWM3N2JmNWFmN2UxZjM3YWUxYmY3MzAzZjVj
|
10
|
+
YjJhYTM5NmU4ZmRkMmI3N2U0ZjlmMzgyODVlZDljMGNhNzA2MWQzYzgzY2Rl
|
11
|
+
ODI3NDYzYmRmNGZkMDNiYzg3ZDRmMWE5M2NkNGFkNmI5MDg0M2M=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZjU4MTZhZWMzNjFiYzllYjAzOTVjZGJkMGEzMzUyYzM3Mzc1NzY2MDVmMWVh
|
14
|
+
OTU1OGNmNTNiYzg5OTQyMGNhZjk5ZjY0YzBiMGViNTQyZGIyZDI2ZjRlMWE4
|
15
|
+
M2RjYWU5ZDY4MTYxMzY3NDhlNjM2MDRhYWY4Y2Q1NWZjYmY0ODk=
|
data/README.md
CHANGED
@@ -25,11 +25,19 @@ The plugin offers 2 actions:
|
|
25
25
|
Use `create` and specify a standard Chef query like `roles:webserver AND chef_environment:prod` and a set of space-separated
|
26
26
|
tags (like `maintenance offline`) in order to tag all nodes retrieved from the search with the specified tags.
|
27
27
|
|
28
|
-
* knife tag bulk delete QUERY TAG1 TAG2 ...
|
28
|
+
* knife tag bulk delete QUERY TAG1 TAG2 ... (options)
|
29
29
|
|
30
30
|
Use `delete` and specify a standard Chef query like `roles:webserver AND chef_environment:prod` and a set of space-separated
|
31
31
|
tags (like `maintenance offline`) in order to remove those tags from all nodes retrieved from the search.
|
32
32
|
|
33
|
+
There is also the possiblity to use Regular Expressions to remove tags based on them. Just specify the `-r` switch and then
|
34
|
+
describe the tags in Regular Expression format. Since there is great posbbility that your shell may escape them though, it's
|
35
|
+
best if you enclose them in quotes. Specifying `-y` in addition to `-r` will skip delete confirmation.
|
36
|
+
|
37
|
+
An example RE-based command is formed like this:
|
38
|
+
|
39
|
+
knife tag bulk delete 'roles:web_old_infrastructure' 'version-deployed-.*' -r -V
|
40
|
+
|
33
41
|
Things to notice
|
34
42
|
----------------
|
35
43
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
@@ -40,38 +40,26 @@ class Chef
|
|
40
40
|
end
|
41
41
|
|
42
42
|
escaped_query = URI.escape(@query,Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
|
43
|
-
|
43
|
+
query = Chef::Search::Query.new
|
44
44
|
node_items = []
|
45
45
|
node_count = 0
|
46
46
|
begin
|
47
|
-
res =
|
48
|
-
node_items = res.first.map { |node| node.name }
|
47
|
+
res = query.search(:node, escaped_query)
|
48
|
+
node_items = res.first.map { |node| node.name }.sort
|
49
49
|
node_count = res.last
|
50
|
-
|
51
|
-
ui.color("\u2192 ", [:bold, :green]) +
|
52
|
-
ui.color(node_count.to_s, [:bold, :yellow]) +
|
53
|
-
ui.color(' node(s) found.', [:bold, :white])
|
54
|
-
)
|
50
|
+
nodes_found(node_count)
|
55
51
|
if node_count > 0
|
56
52
|
node_items.each do |node_name|
|
57
53
|
node = Chef::Node.load(node_name)
|
54
|
+
if (node.tags & @tags).size == @tags.size
|
55
|
+
tags_already_present(node_name, @tags)
|
56
|
+
next
|
57
|
+
end
|
58
58
|
@tags.each { |tag| (node.tags << tag).uniq! }
|
59
59
|
node.save
|
60
|
-
|
61
|
-
ui.color("\u2714 ", [:bold, :green]) +
|
62
|
-
ui.color("Successfully applied tag(s) ", [:bold, :white]) +
|
63
|
-
ui.color("[#{@tags.join(', ')}]", [:bold, :yellow]) +
|
64
|
-
ui.color(" to node ", [:bold, :white]) +
|
65
|
-
ui.color("[#{node_name}]", [:bold, :yellow])
|
66
|
-
)
|
60
|
+
tags_successfully_added(node_name, @tags)
|
67
61
|
if config[:verbosity] > 0
|
68
|
-
|
69
|
-
ui.color("\u2192 ", [:bold, :green]) +
|
70
|
-
ui.color('Node ', [:bold, :white]) +
|
71
|
-
ui.color("[#{node_name}]", [:bold, :yellow]) +
|
72
|
-
ui.color(' is now tagged with ', [:bold, :white]) +
|
73
|
-
ui.color("[#{node.tags.join(', ')}]", [:bold, :yellow])
|
74
|
-
)
|
62
|
+
verbose_node_tag_information(node_name, node.tags)
|
75
63
|
end
|
76
64
|
end
|
77
65
|
end
|
@@ -82,6 +70,45 @@ class Chef
|
|
82
70
|
end
|
83
71
|
end
|
84
72
|
|
73
|
+
def nodes_found(node_count)
|
74
|
+
ui.info(
|
75
|
+
ui.color("\u2192 ", [:bold, :green]) +
|
76
|
+
ui.color(node_count.to_s, [:bold, :yellow]) +
|
77
|
+
ui.color(' node(s) found.', [:bold, :white])
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
def tags_already_present(node_name, tags)
|
82
|
+
ui.info(
|
83
|
+
ui.color("\u2714 ", [:bold, :green]) +
|
84
|
+
ui.color('Node ', [:bold, :white]) +
|
85
|
+
ui.color("[#{node_name}]", [:bold, :yellow]) +
|
86
|
+
ui.color(' is already tagged with ', [:bold, :white]) +
|
87
|
+
ui.color("[#{tags.join(', ')}]", [:bold, :yellow]) +
|
88
|
+
ui.color(". Skipping...", [:bold, :white])
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
def tags_successfully_added(node_name, tags)
|
93
|
+
ui.info(
|
94
|
+
ui.color("\u2714 ", [:bold, :green]) +
|
95
|
+
ui.color("Successfully added tag(s) ", [:bold, :white]) +
|
96
|
+
ui.color("[#{tags.join(', ')}]", [:bold, :yellow]) +
|
97
|
+
ui.color(" to node ", [:bold, :white]) +
|
98
|
+
ui.color("[#{node_name}]", [:bold, :yellow])
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
def verbose_node_tag_information(node_name, tags)
|
103
|
+
ui.info(
|
104
|
+
ui.color("\u2192 ", [:bold, :green]) +
|
105
|
+
ui.color('Node ', [:bold, :white]) +
|
106
|
+
ui.color("[#{node_name}]", [:bold, :yellow]) +
|
107
|
+
ui.color(' is now tagged with ', [:bold, :white]) +
|
108
|
+
ui.color("[#{tags.join(', ')}]", [:bold, :yellow])
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
85
112
|
end
|
86
113
|
end
|
87
114
|
end
|
@@ -26,9 +26,23 @@ class Chef
|
|
26
26
|
require 'chef/search/query'
|
27
27
|
end
|
28
28
|
|
29
|
-
banner 'knife tag bulk delete QUERY TAG ...'
|
29
|
+
banner 'knife tag bulk delete QUERY TAG ... (options)'
|
30
30
|
category 'tag'
|
31
31
|
|
32
|
+
option :regex,
|
33
|
+
:short => '-r',
|
34
|
+
:long => '--regex-match',
|
35
|
+
:description => 'Specify a tag regular expression to match to instead of exact tags to delete',
|
36
|
+
:boolean => true,
|
37
|
+
:default => false
|
38
|
+
|
39
|
+
option :yes,
|
40
|
+
:short => '-y',
|
41
|
+
:long => '--yes',
|
42
|
+
:description => 'Do not prompt for delete confirmation when specifying a tag regular expression match',
|
43
|
+
:boolean => true,
|
44
|
+
:default => false
|
45
|
+
|
32
46
|
def run
|
33
47
|
@query = @name_args.shift
|
34
48
|
@tags = @name_args
|
@@ -40,38 +54,49 @@ class Chef
|
|
40
54
|
end
|
41
55
|
|
42
56
|
escaped_query = URI.escape(@query,Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
|
43
|
-
|
57
|
+
query = Chef::Search::Query.new
|
44
58
|
node_items = []
|
45
59
|
node_count = 0
|
46
60
|
begin
|
47
|
-
res =
|
48
|
-
node_items = res.first.map
|
61
|
+
res = query.search(:node, escaped_query)
|
62
|
+
node_items = res.first.map{ |node| node.name }.sort
|
49
63
|
node_count = res.last
|
50
|
-
|
51
|
-
ui.color("\u2192 ", [:bold, :green]) +
|
52
|
-
ui.color(node_count.to_s, [:bold, :yellow]) +
|
53
|
-
ui.color(' node(s) found.', [:bold, :white])
|
54
|
-
)
|
64
|
+
nodes_found(node_count)
|
55
65
|
if node_count > 0
|
56
|
-
|
66
|
+
if config[:regex]
|
67
|
+
unless config[:yes]
|
68
|
+
confirm = ui.ask_question(
|
69
|
+
ui.color("\u2192 Deleting tags based on regulard expressions is a potentially dangerous operation. Are you sure you want to continue? ", [:bold, :red]),
|
70
|
+
{:default => 'Y'}
|
71
|
+
)
|
72
|
+
if not confirm.match(/[Yy][Ee]?[Ss]?/)
|
73
|
+
ui.fatal('Did not confirm destructive operation. Exiting...')
|
74
|
+
exit 1
|
75
|
+
end
|
76
|
+
end
|
77
|
+
rtags = @tags.map { |rtag| Regexp.new(rtag) }
|
78
|
+
end
|
79
|
+
node_items.each do |node_name|
|
57
80
|
node = Chef::Node.load(node_name)
|
58
|
-
|
81
|
+
tags_to_remove = Array.new
|
82
|
+
if config[:regex]
|
83
|
+
tags_to_remove = node.tags.map do |ntag|
|
84
|
+
rtags.map do |utag|
|
85
|
+
break ntag if ntag.match(utag)
|
86
|
+
end
|
87
|
+
end.flatten.compact.uniq
|
88
|
+
else
|
89
|
+
tags_to_remove = @tags
|
90
|
+
end
|
91
|
+
if (node.tags & tags_to_remove).size == 0
|
92
|
+
tags_not_present(node_name, @tags)
|
93
|
+
next
|
94
|
+
end
|
95
|
+
tags_to_remove.each { |tag| node.tags.delete(tag) }
|
59
96
|
node.save
|
60
|
-
|
61
|
-
ui.color("\u2714 ", [:bold, :green]) +
|
62
|
-
ui.color("Successfully deleted tag(s) ", [:bold, :white]) +
|
63
|
-
ui.color("[#{@tags.join(', ')}]", [:bold, :yellow]) +
|
64
|
-
ui.color(" from node ", [:bold, :white]) +
|
65
|
-
ui.color("[#{node_name}]", [:bold, :yellow])
|
66
|
-
)
|
97
|
+
tags_successfully_deleted(node_name, tags_to_remove)
|
67
98
|
if config[:verbosity] > 0
|
68
|
-
|
69
|
-
ui.color("\u2192 ", [:bold, :green]) +
|
70
|
-
ui.color('Node ', [:bold, :white]) +
|
71
|
-
ui.color("[#{node_name}]", [:bold, :yellow]) +
|
72
|
-
ui.color(' is now tagged with ', [:bold, :white]) +
|
73
|
-
ui.color("[#{node.tags.join(', ')}]", [:bold, :yellow])
|
74
|
-
)
|
99
|
+
verbose_node_tag_information(node_name, node.tags)
|
75
100
|
end
|
76
101
|
end
|
77
102
|
end
|
@@ -79,9 +104,50 @@ class Chef
|
|
79
104
|
msg = Chef::JSONCompat.from_json(e.response.body)['error'].first
|
80
105
|
ui.fatal("An error occurred: #{msg}")
|
81
106
|
exit 1
|
107
|
+
rescue RegexpError => e
|
108
|
+
ui.fatal("Invalid Regular expression given: #{e.message}")
|
82
109
|
end
|
83
110
|
end
|
84
111
|
|
112
|
+
def nodes_found(node_count)
|
113
|
+
ui.info(
|
114
|
+
ui.color("\u2192 ", [:bold, :green]) +
|
115
|
+
ui.color(node_count.to_s, [:bold, :yellow]) +
|
116
|
+
ui.color(' node(s) found.', [:bold, :white])
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
def tags_not_present(node_name, tags)
|
121
|
+
ui.info(
|
122
|
+
ui.color("\u2714 ", [:bold, :green]) +
|
123
|
+
ui.color("Tag(s) ", [:bold, :white]) +
|
124
|
+
ui.color("[#{tags.join(', ')}]", [:bold, :yellow]) +
|
125
|
+
ui.color(" not present on node ", [:bold, :white]) +
|
126
|
+
ui.color("[#{node_name}]", [:bold, :yellow]) +
|
127
|
+
ui.color(". Skipping...", [:bold, :white])
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
def tags_successfully_deleted(node_name, tags)
|
132
|
+
ui.info(
|
133
|
+
ui.color("\u2714 ", [:bold, :green]) +
|
134
|
+
ui.color("Successfully deleted tag(s) ", [:bold, :white]) +
|
135
|
+
ui.color("[#{tags.join(', ')}]", [:bold, :yellow]) +
|
136
|
+
ui.color(" from node ", [:bold, :white]) +
|
137
|
+
ui.color("[#{node_name}]", [:bold, :yellow])
|
138
|
+
)
|
139
|
+
end
|
140
|
+
|
141
|
+
def verbose_node_tag_information(node_name, tags)
|
142
|
+
ui.info(
|
143
|
+
ui.color("\u2192 ", [:bold, :green]) +
|
144
|
+
ui.color('Node ', [:bold, :white]) +
|
145
|
+
ui.color("[#{node_name}]", [:bold, :yellow]) +
|
146
|
+
ui.color(' is now tagged with ', [:bold, :white]) +
|
147
|
+
ui.color("[#{tags.join(', ')}]", [:bold, :yellow])
|
148
|
+
)
|
149
|
+
end
|
150
|
+
|
85
151
|
end
|
86
152
|
end
|
87
153
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-tagbulk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Panagiotis Papadomitsos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-03-
|
11
|
+
date: 2013-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef
|