knife-tagbulk 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|