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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZTQ4ZDVkN2IzMzVmM2Y1YTY4NWZmOGNmYTA2NzEyZjUzZjUzMzJkOQ==
4
+ MjllMjZlZmMzZDE4MzAzOTQwYmI0MTRkNDc2YWZmM2Q5NGI1MmI5ZQ==
5
5
  data.tar.gz: !binary |-
6
- ZDMzYzUyM2JjZmJhYTRjMGUzNjg5YjFkODBjM2E0MjIzMmEwYjJlNg==
6
+ NGE3MjFhNDJhNmI2YjY1YTdiODQwMzU3YTYzMzkwNjRiOWJhMzRkZg==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- M2IzMWUzZTYyNTYzNzkwM2QxYTQ1YTI5ODhmM2E2ZGQ2MjQ4Nzk0OWFlN2Zi
10
- NWI4YTU4NjQ0OTQ4NzE0YWViYjIyMWM4ZjlmYzcyM2ZjMWIxMGFiODAwYWJi
11
- NzE3NmE3YTkxMTEyZDBkYzFmMzcyNmE3ZDJkN2FmMzUwZjNkZDY=
9
+ MWQ5NzkwYjBlMDNjZmFhOGM3MWM3N2JmNWFmN2UxZjM3YWUxYmY3MzAzZjVj
10
+ YjJhYTM5NmU4ZmRkMmI3N2U0ZjlmMzgyODVlZDljMGNhNzA2MWQzYzgzY2Rl
11
+ ODI3NDYzYmRmNGZkMDNiYzg3ZDRmMWE5M2NkNGFkNmI5MDg0M2M=
12
12
  data.tar.gz: !binary |-
13
- NTI4NTU2MDJjYTdjYzQwMWM4MDI4Y2IxMjhmMzMwZDBkNTJhZjk5ZTg5YTg1
14
- MmM5MjJjNDRiNjM0M2NmMjBlMjZiN2FmYjU5MDU2YTUxODQ1OTk5NTgwMjk3
15
- ZmJiZDI4OWI2NDg5NDIzNDc0ZGJjYjA3ZmJiMTg3NzgyYjliY2Q=
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
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
- q = Chef::Search::Query.new
43
+ query = Chef::Search::Query.new
44
44
  node_items = []
45
45
  node_count = 0
46
46
  begin
47
- res = q.search(:node, escaped_query)
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
- ui.info(
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
- ui.info(
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
- ui.info(
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
- q = Chef::Search::Query.new
57
+ query = Chef::Search::Query.new
44
58
  node_items = []
45
59
  node_count = 0
46
60
  begin
47
- res = q.search(:node, escaped_query)
48
- node_items = res.first.map { |node| node.name }
61
+ res = query.search(:node, escaped_query)
62
+ node_items = res.first.map{ |node| node.name }.sort
49
63
  node_count = res.last
50
- ui.info(
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
- node_items.each do |node_name|
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
- @tags.each { |tag| node.tags.delete(tag) }
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
- ui.info(
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
- ui.info(
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.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-07 00:00:00.000000000 Z
11
+ date: 2013-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef