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 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