loe-iclassify-interface 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,5 @@
1
+ === 1.0.0 / 2008-12-08
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
data/Manifest.txt ADDED
@@ -0,0 +1,11 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ iclassify-interface.gemspec
6
+ lib/iclassify-interface.rb
7
+ lib/iclassify-interface/agent.rb
8
+ lib/iclassify-interface/client.rb
9
+ lib/iclassify-interface/node.rb
10
+ lib/iclassify-interface/version.rb
11
+ test/test_iclassify-interface.rb
data/README.txt ADDED
@@ -0,0 +1,36 @@
1
+ = iclassify-interface
2
+
3
+ http://github.com/loe/iclassify-interface
4
+
5
+ == DESCRIPTION:
6
+
7
+ Module for interfacing with iclassify.
8
+
9
+ == INSTALL:
10
+
11
+ sudo gem install loe-iclassify-interface
12
+
13
+ == LICENSE:
14
+
15
+ (The MIT License)
16
+
17
+ Copyright (c) 2008 FIX
18
+
19
+ Permission is hereby granted, free of charge, to any person obtaining
20
+ a copy of this software and associated documentation files (the
21
+ 'Software'), to deal in the Software without restriction, including
22
+ without limitation the rights to use, copy, modify, merge, publish,
23
+ distribute, sublicense, and/or sell copies of the Software, and to
24
+ permit persons to whom the Software is furnished to do so, subject to
25
+ the following conditions:
26
+
27
+ The above copyright notice and this permission notice shall be
28
+ included in all copies or substantial portions of the Software.
29
+
30
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
31
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
33
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
34
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
35
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
36
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+
4
+ LIB_DIR = File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
5
+ $LOAD_PATH << LIB_DIR
6
+
7
+ require 'iclassify-interface/version'
8
+
9
+ HOE = Hoe.new('iclassify-interface', IClassify::VERSION) do |p|
10
+ p.name = "iclassify-interface"
11
+ p.author = "W. Andrew Loe III"
12
+ p.email = "loe@onehub.com"
13
+ p.summary = "Module for interfacing with an iclassify server."
14
+ end
15
+
16
+ # Cribbed from nokogiri
17
+ namespace :gem do
18
+ task :spec do
19
+ File.open("#{HOE.name}.gemspec", 'w') do |f|
20
+ f.write(HOE.spec.to_ruby)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{iclassify-interface}
3
+ s.version = "1.0.0"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["W. Andrew Loe III"]
7
+ s.date = %q{2008-12-08}
8
+ s.description = %q{Module for interfacing with iclassify.}
9
+ s.email = %q{loe@onehub.com}
10
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
11
+ s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "iclassify-interface.gemspec", "lib/iclassify-interface.rb", "lib/iclassify-interface/agent.rb", "lib/iclassify-interface/client.rb", "lib/iclassify-interface/node.rb", "lib/iclassify-interface/version.rb", "test/test_iclassify-interface.rb"]
12
+ s.has_rdoc = true
13
+ s.homepage = %q{http://github.com/loe/iclassify-interface}
14
+ s.rdoc_options = ["--main", "README.txt"]
15
+ s.require_paths = ["lib"]
16
+ s.rubyforge_project = %q{iclassify-interface}
17
+ s.rubygems_version = %q{1.2.0}
18
+ s.summary = %q{Module for interfacing with an iclassify server.}
19
+ s.test_files = ["test/test_iclassify-interface.rb"]
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 2
24
+
25
+ if current_version >= 3 then
26
+ s.add_development_dependency(%q<hoe>, [">= 1.8.2"])
27
+ else
28
+ s.add_dependency(%q<hoe>, [">= 1.8.2"])
29
+ end
30
+ else
31
+ s.add_dependency(%q<hoe>, [">= 1.8.2"])
32
+ end
33
+ end
@@ -0,0 +1,4 @@
1
+ require 'iclassify-interface/agent'
2
+ require 'iclassify-interface/client'
3
+ require 'iclassify-interface/node'
4
+ require 'iclassify-interface/version'
@@ -0,0 +1,155 @@
1
+ require 'rubygems'
2
+ require 'uuidtools'
3
+
4
+ module IClassify
5
+ class Agent
6
+ attr_accessor :node
7
+ attr_accessor :uuid
8
+ attr_accessor :password
9
+
10
+ #
11
+ # Create a new Agent. Takes a path to a file to either read or drop
12
+ # a UUID, and a server URL.
13
+ #
14
+ def initialize(uuidfile="/etc/icagent/icagent.uuid", server_url="http://localhost:3000")
15
+ @uuid = nil
16
+ @password = nil
17
+ if File.exists?(uuidfile)
18
+ IO.foreach(uuidfile) do |line|
19
+ @uuid, @password = line.chomp.split("!")
20
+ end
21
+ unless @password
22
+ @password = random_password(30)
23
+ write_uuidfile(uuidfile)
24
+ end
25
+ else
26
+ @uuid = UUID.random_create
27
+ @password = random_password(30)
28
+ write_uuidfile(uuidfile)
29
+ end
30
+ @client = IClassify::Client.new(server_url, @uuid, @password)
31
+ end
32
+
33
+ #
34
+ # Loads data about this node from the iClassify service
35
+ #
36
+ def load
37
+ begin
38
+ @node = @client.get_node(@uuid)
39
+ rescue Net::HTTPServerException => e
40
+ if e.to_s =~ /^404/
41
+ @node = IClassify::Node.new()
42
+ @node.description = "New Node"
43
+ @node.tags << "unclassified"
44
+ @node.password = @password
45
+ @node.uuid = @uuid
46
+ else
47
+ throw(e)
48
+ end
49
+ end
50
+ end
51
+
52
+ #
53
+ # Updates this node in the iClassify service.
54
+ #
55
+ def update
56
+ if @node.description == "New Node"
57
+ hostname = attrib?("hostname")
58
+ hostname ||= "New Node"
59
+ @node.description = hostname
60
+ end
61
+ @client.update_node(@node)
62
+ end
63
+
64
+ #
65
+ # Deletes this node from the iClassify service.
66
+ #
67
+ def delete
68
+ @client.delete_node(@node)
69
+ end
70
+
71
+ #
72
+ # Returns the tag name if this node has that tag.
73
+ #
74
+ def tag?(tag)
75
+ @node.tag?(tag)
76
+ end
77
+
78
+ # Returns the values for this attribute, if it exists for this node. If
79
+ # there is only one, it will return it, if it's an array, you get the
80
+ # array. You have to check!
81
+ def attrib?(attrib)
82
+ @node.attrib?(attrib)
83
+ end
84
+
85
+ # Returns the current node as a string.
86
+ def to_s
87
+ @node.to_s
88
+ end
89
+
90
+ # Returns the value if the given attribute has a given attribute.
91
+ def attrib_has_value?(attrib, value)
92
+ na = @node.attribs.detect { |a| a[:name] == attrib }
93
+ if na
94
+ return na.values.detect { |v| v == value}
95
+ else
96
+ return nil
97
+ end
98
+ end
99
+
100
+ # Add a tag to this node.
101
+ def add_tag(tag)
102
+ load unless @node
103
+ @node.tags << tag
104
+ end
105
+
106
+ # Add an attribute to this node. Requires a name and either a string or
107
+ # array of values.
108
+ #
109
+ # Will be cumulative!
110
+ def add_attrib(name, values)
111
+ load unless @node
112
+ @node.attribs << { :name => name, :values => values.kind_of?(Array) ? values : [ values ] }
113
+ end
114
+
115
+ # Replace the attribute with the given name's values in place.
116
+ # Will add a new attribute if it needs to.
117
+ def replace_attrib(name, values)
118
+ exists = @node.attribs.detect { |a| a[:name] == name }
119
+ if exists
120
+ exists[:values] = values.kind_of?(Array) ? values : [ values ]
121
+ else
122
+ add_attrib(name, values)
123
+ end
124
+ end
125
+
126
+ # Set the description for the node
127
+ def description(value)
128
+ @node.description = value
129
+ end
130
+
131
+ # return the value of @node.description
132
+ def description?()
133
+ @node.description
134
+ end
135
+
136
+ # Run an iclassify script.
137
+ def run_script(scriptfile)
138
+ eval(IO.read(scriptfile))
139
+ end
140
+
141
+ protected
142
+ def random_password(len)
143
+ chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
144
+ newpass = ""
145
+ 1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
146
+ newpass
147
+ end
148
+
149
+ def write_uuidfile(uuidfile)
150
+ File.open(uuidfile, "w") do |file|
151
+ file.puts "#{@uuid}!#{@password}"
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,108 @@
1
+ require 'rubygems'
2
+ require 'net/https'
3
+ require 'rexml/document'
4
+ require 'uri'
5
+ require 'yaml'
6
+
7
+ module IClassify
8
+
9
+ class Client
10
+ UUID_REGEX = /^[[:xdigit:]]{8}[:-][[:xdigit:]]{4}[:-][[:xdigit:]]{4}[:-][[:xdigit:]]{4}[:-][[:xdigit:]]{12}$/
11
+
12
+ def initialize(service_url, username, password)
13
+ service_url = "#{service_url}/rest" unless service_url =~ /rest$/
14
+ @url = URI.parse(service_url)
15
+ @username = username
16
+ @password = password
17
+ end
18
+
19
+ def make_url(method, params)
20
+ params[:appid] = @appid
21
+ super method, params
22
+ end
23
+
24
+ def search(query, attribs=[])
25
+ raise ArgumentError, "Attributes must be given as a list!" unless attribs.kind_of?(Array)
26
+ querystring = "search"
27
+ querystring << "?q=#{URI.escape(query)}"
28
+ querystring << "&a=#{URI.escape(attribs.join(','))}" if attribs.length > 0
29
+ results = get_rest(querystring, "text/yaml")
30
+ node_array = YAML.load(results).collect { |n| IClassify::Node.new(:yaml, n) }
31
+ end
32
+
33
+ def get_node(node_id)
34
+ IClassify::Node.new(:xml, get_rest("nodes/#{node_id}"))
35
+ end
36
+
37
+ def update_node(node)
38
+ if node.node_id
39
+ put_rest("nodes/#{node.node_id}", node.to_xml)
40
+ else
41
+ post_rest("nodes", node.to_xml)
42
+ end
43
+ end
44
+
45
+ def delete_node(node)
46
+ delete_rest("nodes/#{node.node_id}")
47
+ end
48
+
49
+ private
50
+
51
+ def get_rest(path, accept="application/xml")
52
+ url = URI.parse("#{@url}/#{path}")
53
+ run_request(:GET, url, false, accept)
54
+ end
55
+
56
+ def delete_rest(path, accept="application/xml")
57
+ url = URI.parse("#{@url}/#{path}")
58
+ run_request(:DELETE, url, false, accept)
59
+ end
60
+
61
+ def post_rest(path, xml, accept="application/xml")
62
+ url = URI.parse("#{@url}/#{path}")
63
+ run_request(:POST, url, xml, accept)
64
+ end
65
+
66
+ def put_rest(path, xml, accept="application/xml")
67
+ url = URI.parse("#{@url}/#{path}")
68
+ run_request(:PUT, url, xml, accept)
69
+ end
70
+
71
+ def run_request(method, url, data=false, accept="application/xml")
72
+ http = Net::HTTP.new(url.host, url.port)
73
+ if url.scheme == "https"
74
+ http.use_ssl = true
75
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
76
+ end
77
+ http.read_timeout = 60
78
+ headers = {
79
+ 'Accept' => accept,
80
+ 'Content-Type' => accept
81
+ }
82
+ req = nil
83
+ case method
84
+ when :GET
85
+ req_path = "#{url.path}"
86
+ req_path << "?#{url.query}" if url.query
87
+ req = Net::HTTP::Get.new(req_path, headers)
88
+ when :POST
89
+ req = Net::HTTP::Post.new(url.path, headers)
90
+ req.body = data if data
91
+ when :PUT
92
+ req = Net::HTTP::Put.new(url.path, headers)
93
+ req.body = data if data
94
+ when :DELETE
95
+ req = Net::HTTP::Delete.new(url.path, headers)
96
+ end
97
+ req.basic_auth(@username, @password)
98
+ res = http.request(req)
99
+ case res
100
+ when Net::HTTPSuccess
101
+ res.body
102
+ else
103
+ res.error!
104
+ end
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,134 @@
1
+ require 'rubygems'
2
+ require 'rexml/document'
3
+ require 'builder'
4
+ require 'yaml'
5
+ require 'digest/sha1'
6
+
7
+ module IClassify
8
+ class Node
9
+ attr_accessor :tags, :uuid, :description, :notes, :attribs, :node_id, :password
10
+
11
+ def initialize(type=:xml, data=nil)
12
+ from_xml(data) if type == :xml && data
13
+ from_yaml(data) if type == :yaml && data
14
+ @tags ||= Array.new
15
+ @attribs ||= Array.new
16
+ @password = nil
17
+ end
18
+
19
+ def to_xml
20
+ xml = Builder::XmlMarkup.new
21
+ output = xml.node do
22
+ xml.id(@node_id) if @node_id
23
+ xml.uuid(@uuid)
24
+ xml.password(@password) if @password
25
+ xml.description(@description)
26
+ xml.notes(@notes)
27
+ xml.tags do
28
+ @tags.sort.each do |tag|
29
+ xml.tag(tag)
30
+ end
31
+ end
32
+ xml.attribs do
33
+ @attribs.sort{ |a,b| a[:name] <=> b[:name] }.each do |attrib|
34
+ xml.attrib do
35
+ xml.name(attrib[:name])
36
+ xml.values do
37
+ attrib[:values].each do |v|
38
+ xml.value(v)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ output
46
+ end
47
+
48
+ def digest
49
+ Digest::SHA1.hexdigest(to_s())
50
+ end
51
+
52
+ #
53
+ # Returns the tag name if this node has that tag.
54
+ #
55
+ def tag?(tag)
56
+ @tags.detect { |t| t == tag }
57
+ end
58
+
59
+ # Returns the values for this attribute, if it exists for this node. If
60
+ # there is only one, it will return it, if it's an array, you get the
61
+ # array. You have to check!
62
+ def attrib?(attrib)
63
+ na = @attribs.detect { |a| a[:name] == attrib }
64
+ return nil unless na
65
+ if na[:values].length > 1
66
+ return na[:values]
67
+ else
68
+ return na[:values][0]
69
+ end
70
+ end
71
+
72
+ def to_s(tags=nil,attribs=[])
73
+ output = String.new
74
+ output << "uuid: #{@uuid}\n"
75
+ output << "node_id: #{@node_id}\n"
76
+ output << "notes: #{@notes}\n"
77
+ output << "description: #{@description}\n"
78
+ output << "tags: #{@tags.sort.join(' ')}\n"
79
+ output << "attribs:\n"
80
+ @attribs.select{ |attrib| attribs.include?(attrib[:name].to_sym) }.sort{ |a,b| a[:name] <=> b[:name] }.each do |attrib|
81
+ output << " #{attrib[:name]}: #{attrib[:values].join(', ')}\n"
82
+ end
83
+ output
84
+ end
85
+
86
+ def to_puppet
87
+ output = Hash.new
88
+ output["classes"] = @tags
89
+ output["parameters"] = Hash.new
90
+ @attribs.each do |attrib|
91
+ if attrib[:values].length > 1
92
+ output["parameters"][attrib[:name]] = attrib[:values]
93
+ else
94
+ output["parameters"][attrib[:name]] = attrib[:values][0]
95
+ end
96
+ end
97
+ output.to_yaml
98
+ end
99
+
100
+ def from_xml(doc)
101
+ xml = nil
102
+ if doc.kind_of?(REXML::Element)
103
+ xml = doc
104
+ else
105
+ xml = REXML::Document.new(doc)
106
+ end
107
+ @tags = Array.new
108
+ xml.elements.each('//tag') { |t| @tags << t.text }
109
+ @uuid = xml.get_text('//uuid')
110
+ @node_id = xml.get_text('//id')
111
+ @description = xml.get_text('//description')
112
+ @notes = xml.get_text('//notes')
113
+ @attribs = Array.new
114
+ xml.elements.each('//attrib') do |attrib|
115
+ cattrib = Hash.new
116
+ cattrib[:name] = attrib.get_text('name').to_s
117
+ value_array = Array.new
118
+ attrib.elements.each('values/value') { |v| value_array << v.text }
119
+ cattrib[:values] = value_array
120
+ @attribs << cattrib
121
+ end
122
+ end
123
+
124
+ def from_yaml(data)
125
+ @tags = data[:tags].collect { |t| t[:name] }
126
+ @uuid = data[:uuid]
127
+ @description = data[:description]
128
+ @notes = data[:notes]
129
+ @attribs = data[:attribs].delete_if { |x| x[:name] == "text" }
130
+ @node_id = data[:id]
131
+ end
132
+
133
+ end
134
+ end
@@ -0,0 +1,3 @@
1
+ module IClassify
2
+ VERSION = '1.0.0'
3
+ end
File without changes
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: loe-iclassify-interface
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - W. Andrew Loe III
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-08 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.8.2
23
+ version:
24
+ description: Module for interfacing with iclassify.
25
+ email: loe@onehub.com
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - History.txt
32
+ - Manifest.txt
33
+ - README.txt
34
+ files:
35
+ - History.txt
36
+ - Manifest.txt
37
+ - README.txt
38
+ - Rakefile
39
+ - iclassify-interface.gemspec
40
+ - lib/iclassify-interface.rb
41
+ - lib/iclassify-interface/agent.rb
42
+ - lib/iclassify-interface/client.rb
43
+ - lib/iclassify-interface/node.rb
44
+ - lib/iclassify-interface/version.rb
45
+ - test/test_iclassify-interface.rb
46
+ has_rdoc: true
47
+ homepage: http://github.com/loe/iclassify-interface
48
+ post_install_message:
49
+ rdoc_options:
50
+ - --main
51
+ - README.txt
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements: []
67
+
68
+ rubyforge_project: iclassify-interface
69
+ rubygems_version: 1.2.0
70
+ signing_key:
71
+ specification_version: 2
72
+ summary: Module for interfacing with an iclassify server.
73
+ test_files:
74
+ - test/test_iclassify-interface.rb