occi 2.2.2 → 2.3.0
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.
- data/.yardopts +1 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -2
- data/README.md +48 -18
- data/lib/occi/client.rb +54 -17
- data/lib/occi/collection.rb +25 -7
- data/lib/occi/core/action.rb +7 -0
- data/lib/occi/core/attribute_properties.rb +2 -2
- data/lib/occi/core/attributes.rb +2 -2
- data/lib/occi/core/category.rb +43 -23
- data/lib/occi/core/entity.rb +62 -67
- data/lib/occi/core/kind.rb +32 -5
- data/lib/occi/core/link.rb +14 -51
- data/lib/occi/core/mixin.rb +31 -5
- data/lib/occi/core/resource.rb +34 -33
- data/lib/occi/log.rb +16 -4
- data/lib/occi/model.rb +53 -47
- data/lib/occi/parser.rb +192 -65
- data/lib/occi/version.rb +1 -1
- data/spec/occi/client_spec.rb +12 -0
- data/spec/occi/log_spec.rb +2 -1
- data/spec/occi/model_spec.rb +43 -14
- data/spec/occi/parser_spec.rb +18 -3
- data/spec/occi/test.ova +0 -0
- metadata +6 -3
data/lib/occi/core/kind.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'json'
|
1
|
+
require 'active_support/json'
|
2
2
|
require 'occi/core/category'
|
3
3
|
require 'occi/core/action'
|
4
4
|
require 'occi/core/attribute_properties'
|
@@ -7,13 +7,22 @@ module OCCI
|
|
7
7
|
module Core
|
8
8
|
class Kind < OCCI::Core::Category
|
9
9
|
|
10
|
-
attr_accessor :entities
|
10
|
+
attr_accessor :entities, :related, :actions
|
11
11
|
|
12
|
-
|
12
|
+
# @param [String ] scheme
|
13
|
+
# @param [String] term
|
14
|
+
# @param [String] title
|
15
|
+
# @param [OCCI::Core::AttributeProperties] attributes
|
16
|
+
# @param [Array] related
|
17
|
+
# @param [Array] actions
|
18
|
+
def initialize(scheme, term, title=nil, attributes=nil, related=nil, actions=nil)
|
13
19
|
@entities = []
|
14
|
-
|
20
|
+
@related = related.to_a
|
21
|
+
@actions = actions.to_a
|
22
|
+
super(scheme, term, title, attributes)
|
15
23
|
end
|
16
24
|
|
25
|
+
# @return [String] name of the OCCI core class the entity is related to
|
17
26
|
def entity_type
|
18
27
|
case type_identifier
|
19
28
|
when "http://schemas.ogf.org/occi/core#resource"
|
@@ -25,8 +34,26 @@ module OCCI
|
|
25
34
|
end
|
26
35
|
end
|
27
36
|
|
37
|
+
# @return [String] string containing location URI of kind
|
28
38
|
def location
|
29
|
-
'/' +
|
39
|
+
'/' + @term + '/'
|
40
|
+
end
|
41
|
+
|
42
|
+
def as_json(options={ })
|
43
|
+
kind = Hashie::Mash.new
|
44
|
+
kind.related = @related if @related.any?
|
45
|
+
kind.actions = @actions if @actions.any?
|
46
|
+
kind.merge! super
|
47
|
+
kind
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_text
|
51
|
+
text = super
|
52
|
+
text << ';rel=' + @related.join(' ').inspect if @related.any?
|
53
|
+
text << ';location=' + self.location.inspect
|
54
|
+
text << ';attributes=' + @attributes.combine.join(' ').inspect if @attributes.any?
|
55
|
+
text << ';actions=' + @actions.join(' ').inspect if @actions.any?
|
56
|
+
text
|
30
57
|
end
|
31
58
|
|
32
59
|
end
|
data/lib/occi/core/link.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'hashie/mash'
|
2
|
-
require 'occi/model'
|
3
2
|
require 'occi/core/entity'
|
4
3
|
require 'occi/core/kind'
|
5
4
|
|
@@ -7,60 +6,24 @@ module OCCI
|
|
7
6
|
module Core
|
8
7
|
class Link < Entity
|
9
8
|
|
10
|
-
#
|
11
|
-
def self.
|
12
|
-
|
13
|
-
data[:actions] = []
|
14
|
-
data[:related] = %w{http://schemas.ogf.org/occi/core#entity}
|
15
|
-
data[:term] = "link"
|
16
|
-
data[:scheme] = "http://schemas.ogf.org/occi/core#"
|
17
|
-
data[:title] = "Link"
|
9
|
+
# @return [OCCI::Core::Kind] kind definition of Link type
|
10
|
+
def self.kind_definition
|
11
|
+
kind = OCCI::Core::Kind.new('http://schemas.ogf.org/occi/core#','link')
|
18
12
|
|
19
|
-
|
20
|
-
|
21
|
-
data.attributes!.occi!.core!.target!.required = false
|
22
|
-
data.attributes!.occi!.core!.target!.mutable = true
|
13
|
+
kind.related = %w{http://schemas.ogf.org/occi/core#entity}
|
14
|
+
kind.title = "Link"
|
23
15
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
16
|
+
kind.attributes.occi!.core!.target!.type = "string"
|
17
|
+
kind.attributes.occi!.core!.target!.pattern = ".*"
|
18
|
+
kind.attributes.occi!.core!.target!.required = false
|
19
|
+
kind.attributes.occi!.core!.target!.mutable = true
|
28
20
|
|
29
|
-
kind =
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
def target
|
34
|
-
return self[:target]
|
35
|
-
end
|
36
|
-
|
37
|
-
def target=(target)
|
38
|
-
self[:target] = target
|
39
|
-
self.attributes!.occi!.core!.target = target
|
40
|
-
end
|
41
|
-
|
42
|
-
def source
|
43
|
-
return self[:source]
|
44
|
-
end
|
45
|
-
|
46
|
-
def source=(source)
|
47
|
-
self[:source] = source
|
48
|
-
self.attributes!.occi!.core!.source = source
|
49
|
-
end
|
21
|
+
kind.attributes.occi!.core!.source!.type = "string"
|
22
|
+
kind.attributes.occi!.core!.source!.pattern = ".*"
|
23
|
+
kind.attributes.occi!.core!.source!.required = false
|
24
|
+
kind.attributes.occi!.core!.source!.mutable = true
|
50
25
|
|
51
|
-
|
52
|
-
case val
|
53
|
-
when self.class
|
54
|
-
val.dup
|
55
|
-
when ::Hash
|
56
|
-
val = val.dup if duping
|
57
|
-
self.class.subkey_class.new.merge(val) unless val.kind_of?(Hashie::Mash)
|
58
|
-
val
|
59
|
-
when Array
|
60
|
-
val.collect { |e| convert_value(e) }
|
61
|
-
else
|
62
|
-
val
|
63
|
-
end
|
26
|
+
kind
|
64
27
|
end
|
65
28
|
|
66
29
|
end
|
data/lib/occi/core/mixin.rb
CHANGED
@@ -1,19 +1,45 @@
|
|
1
|
-
require 'json'
|
1
|
+
require 'active_support/json'
|
2
2
|
require 'occi/core/category'
|
3
3
|
|
4
4
|
module OCCI
|
5
5
|
module Core
|
6
6
|
class Mixin < OCCI::Core::Category
|
7
7
|
|
8
|
-
attr_accessor :entities
|
8
|
+
attr_accessor :entities, :related, :actions
|
9
9
|
|
10
|
-
|
10
|
+
# @param [String ] scheme
|
11
|
+
# @param [String] term
|
12
|
+
# @param [String] title
|
13
|
+
# @param [OCCI::Core::AttributeProperties] attributes
|
14
|
+
# @param [Array] related
|
15
|
+
# @param [Array] actions
|
16
|
+
def initialize(scheme, term, title=nil, attributes=nil, related=nil, actions=nil)
|
11
17
|
@entities = []
|
12
|
-
|
18
|
+
@related = related.to_a
|
19
|
+
@actions = actions.to_a
|
20
|
+
super(scheme, term, title, attributes)
|
13
21
|
end
|
14
22
|
|
23
|
+
# @return [String] string containing location URI of mixin
|
15
24
|
def location
|
16
|
-
'/
|
25
|
+
'/mixins/' + @term + '/'
|
26
|
+
end
|
27
|
+
|
28
|
+
def as_json(options={ })
|
29
|
+
mixin = Hashie::Mash.new
|
30
|
+
mixin.related = @related if @related.any?
|
31
|
+
mixin.actions = @actions if @actions.any?
|
32
|
+
mixin.merge! super
|
33
|
+
mixin
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_text
|
37
|
+
text = super
|
38
|
+
text << ';rel=' + @related.join(' ').inspect if @related.any?
|
39
|
+
text << ';location=' + self.location.inspect
|
40
|
+
text << ';attributes=' + @attributes.combine.join(' ').inspect if @attributes.any?
|
41
|
+
text << ';actions=' + @actions.join(' ').inspect if @actions.any?
|
42
|
+
text
|
17
43
|
end
|
18
44
|
|
19
45
|
end
|
data/lib/occi/core/resource.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'hashie/mash'
|
2
|
-
require '
|
2
|
+
require 'active_support/json'
|
3
3
|
require 'occi/core/entity'
|
4
4
|
require 'occi/core/kind'
|
5
5
|
|
@@ -7,46 +7,47 @@ module OCCI
|
|
7
7
|
module Core
|
8
8
|
class Resource < Entity
|
9
9
|
|
10
|
-
|
11
|
-
data = Hashie::Mash.new
|
12
|
-
data[:related] = %w{http://schemas.ogf.org/occi/core#entity}
|
13
|
-
data[:term] = "resource"
|
14
|
-
data[:scheme] = "http://schemas.ogf.org/occi/core#"
|
15
|
-
data[:title] = "Resource"
|
10
|
+
attr_accessor :links
|
16
11
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
def initialize(kind, mixins=nil, attributes=nil, links=nil)
|
13
|
+
@href = nil
|
14
|
+
@links = links.to_a
|
15
|
+
super(kind, mixins, attributes)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.kind_definition
|
19
|
+
kind = OCCI::Core::Kind.new('http://schemas.ogf.org/occi/core#', 'resource')
|
20
|
+
|
21
|
+
kind.related = %w{http://schemas.ogf.org/occi/core#entity}
|
22
|
+
kind.title = 'Resource'
|
23
|
+
|
24
|
+
kind.attributes.occi!.core!.summary!.type = 'string'
|
25
|
+
kind.attributes.occi!.core!.summary!.pattern = '.*'
|
26
|
+
kind.attributes.occi!.core!.summary!.required = false
|
27
|
+
kind.attributes.occi!.core!.summary!.mutable = true
|
21
28
|
|
22
|
-
kind
|
23
|
-
OCCI::Model.register(kind)
|
29
|
+
kind
|
24
30
|
end
|
25
31
|
|
26
|
-
|
27
|
-
|
28
|
-
|
32
|
+
# set id for resource and update the the source of all links
|
33
|
+
# @param [UUIDTools::UUID] id
|
34
|
+
def id=(id)
|
35
|
+
super(id)
|
36
|
+
@links.each { |link| link.attributes.occi!.core!.source = self.location }
|
29
37
|
end
|
30
38
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
39
|
+
# update the source of all links before returning them
|
40
|
+
# @return [Array] links of resource
|
41
|
+
def links
|
42
|
+
@links.each { |link| link.attributes.occi!.core!.source = self.location }
|
43
|
+
@links
|
35
44
|
end
|
36
45
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
val = val.dup if duping
|
43
|
-
self.class.subkey_class.new.merge(val) unless val.kind_of?(Hashie::Mash)
|
44
|
-
val
|
45
|
-
when Array
|
46
|
-
val.collect { |e| convert_value(e) }
|
47
|
-
else
|
48
|
-
val
|
49
|
-
end
|
46
|
+
def as_json(options={ })
|
47
|
+
resource = Hashie::Mash.new
|
48
|
+
resource.links = @links if @links.any?
|
49
|
+
resource.merge! super
|
50
|
+
resource
|
50
51
|
end
|
51
52
|
|
52
53
|
end
|
data/lib/occi/log.rb
CHANGED
@@ -6,13 +6,17 @@ module OCCI
|
|
6
6
|
|
7
7
|
include Logger::Severity
|
8
8
|
|
9
|
+
attr_reader :logger
|
10
|
+
|
9
11
|
# creates a new OCCI logger
|
10
12
|
# @param [IO,String] logdev The log device. This is a filename (String) or IO object (typically +STDOUT+,
|
11
13
|
# +STDERR+, or an open file).
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
def initialize(logdev)
|
15
|
+
if logdev.kind_of? Logger
|
16
|
+
@logger = logdev
|
17
|
+
else
|
18
|
+
@logger = Logger.new(logdev)
|
19
|
+
end
|
16
20
|
|
17
21
|
# subscribe to log messages and send to logger
|
18
22
|
@log_subscriber = ActiveSupport::Notifications.subscribe("log") do |name, start, finish, id, payload|
|
@@ -20,6 +24,14 @@ module OCCI
|
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
27
|
+
def level=(severity)
|
28
|
+
@logger.level = severity
|
29
|
+
end
|
30
|
+
|
31
|
+
def level
|
32
|
+
@logger.level
|
33
|
+
end
|
34
|
+
|
23
35
|
# @see info
|
24
36
|
def self.debug(message)
|
25
37
|
ActiveSupport::Notifications.instrument("log", :level => Logger::DEBUG, :message => message)
|
data/lib/occi/model.rb
CHANGED
@@ -3,21 +3,28 @@ require 'occi/log'
|
|
3
3
|
|
4
4
|
module OCCI
|
5
5
|
class Model
|
6
|
-
|
7
|
-
|
6
|
+
attr_accessor :categories
|
7
|
+
attr_accessor :locations
|
8
|
+
|
9
|
+
def initialize(collection=nil)
|
10
|
+
@categories = { }
|
11
|
+
@locations = { }
|
12
|
+
register_core
|
13
|
+
register_collection collection if collection
|
14
|
+
end
|
8
15
|
|
9
16
|
# register OCCI Core categories enitity, resource and link
|
10
|
-
def
|
11
|
-
OCCI::Log.info
|
12
|
-
OCCI::Core::Entity.
|
13
|
-
OCCI::Core::Resource.
|
14
|
-
OCCI::Core::Link.
|
17
|
+
def register_core
|
18
|
+
OCCI::Log.info "### Registering OCCI Core categories enitity, resource and link ###"
|
19
|
+
register OCCI::Core::Entity.kind_definition
|
20
|
+
register OCCI::Core::Resource.kind_definition
|
21
|
+
register OCCI::Core::Link.kind_definition
|
15
22
|
end
|
16
23
|
|
17
24
|
# register OCCI Infrastructure categories
|
18
|
-
def
|
19
|
-
OCCI::Log.info
|
20
|
-
|
25
|
+
def register_infrastructure
|
26
|
+
OCCI::Log.info "### Registering OCCI Infrastructure categories ###"
|
27
|
+
register_files 'etc/model/infrastructure'
|
21
28
|
end
|
22
29
|
|
23
30
|
# register OCCI categories from files
|
@@ -25,81 +32,80 @@ module OCCI
|
|
25
32
|
# @param [String] path to a folder containing files which include OCCI collections in JSON format. The path is
|
26
33
|
# recursively searched for files with the extension .json .
|
27
34
|
# @param [Sting] scheme_base_url base location for provider specific extensions of the OCCI model
|
28
|
-
def
|
29
|
-
OCCI::Log.info
|
35
|
+
def register_files(path, scheme_base_url='http://localhost')
|
36
|
+
OCCI::Log.info "### Initializing OCCI Model from #{path} ###"
|
30
37
|
Dir.glob(path + '/**/*.json').each do |file|
|
31
38
|
collection = OCCI::Collection.new(JSON.parse(File.read(file)))
|
32
39
|
# add location of service provider to scheme if it has a relative location
|
33
40
|
collection.kinds.collect { |kind| kind.scheme = scheme_base_url + kind.scheme if kind.scheme.start_with? '/' } if collection.kinds
|
34
41
|
collection.mixins.collect { |mixin| mixin.scheme = scheme_base_url + mixin.scheme if mixin.scheme.start_with? '/' } if collection.mixins
|
35
42
|
collection.actions.collect { |action| action.scheme = scheme_base_url + action.scheme if action.scheme.start_with? '/' } if collection.actions
|
36
|
-
|
43
|
+
register_collection collection
|
37
44
|
end
|
38
45
|
end
|
39
46
|
|
40
47
|
# register OCCI categories from OCCI collection
|
41
|
-
def
|
42
|
-
collection.
|
43
|
-
collection.mixins.each { |mixin| self.register(OCCI::Core::Mixin.new(mixin)) } if collection.mixins
|
44
|
-
collection.actions.each { |action| self.register(OCCI::Core::Action.new(action)) } if collection.actions
|
48
|
+
def register_collection(collection)
|
49
|
+
collection.categories.each { |category| register category }
|
45
50
|
end
|
46
51
|
|
47
|
-
def
|
48
|
-
|
52
|
+
def reset()
|
53
|
+
@categories.each_value.each { |category| category.entities = [] if category.entities }
|
49
54
|
end
|
50
55
|
|
51
56
|
# ---------------------------------------------------------------------------------------------------------------------
|
52
|
-
def
|
53
|
-
OCCI::Log.debug
|
54
|
-
|
55
|
-
|
57
|
+
def register(category)
|
58
|
+
OCCI::Log.debug "### Registering category #{category.type_identifier}"
|
59
|
+
@categories[category.type_identifier] = category
|
60
|
+
@locations[category.location] = category.type_identifier unless category.kind_of? OCCI::Core::Action
|
56
61
|
end
|
57
62
|
|
58
63
|
# ---------------------------------------------------------------------------------------------------------------------
|
59
|
-
def
|
60
|
-
OCCI::Log.debug
|
61
|
-
|
62
|
-
|
64
|
+
def unregister(category)
|
65
|
+
OCCI::Log.debug "### Unregistering category #{category.type_identifier}"
|
66
|
+
@categories.delete category.type_identifier
|
67
|
+
@locations.delete category.location unless category.kind_of? OCCI :Core::Action
|
63
68
|
end
|
64
69
|
|
65
70
|
# Returns the category corresponding to a given type identifier
|
66
71
|
#
|
67
72
|
# @param [URI] type identifier of a category
|
68
|
-
def
|
69
|
-
|
73
|
+
def get_by_id(id)
|
74
|
+
@categories.fetch(id) { OCCI::Log.debug("Category with id #{id} not found"); nil }
|
70
75
|
end
|
71
76
|
|
72
77
|
# Returns the category corresponding to a given location
|
73
78
|
#
|
74
79
|
# @param [URI] Location of a category
|
75
|
-
def
|
76
|
-
id =
|
77
|
-
|
80
|
+
def get_by_location(location)
|
81
|
+
id = @locations.fetch(location) { OCCI::Log.debug("Category with location #{location} not found"); nil }
|
82
|
+
get_by_id id
|
78
83
|
end
|
79
84
|
|
80
85
|
# Return all categories from model. If filter is present, return only the categories specified by filter
|
81
86
|
#
|
82
|
-
# @param [
|
83
|
-
# @return [
|
84
|
-
def
|
85
|
-
collection =
|
87
|
+
# @param [OCCI::Collection] filter
|
88
|
+
# @return [OCCI::Collection] collection
|
89
|
+
def get(filter = [])
|
90
|
+
collection = OCCI::Collection.new
|
86
91
|
if filter.empty?
|
87
|
-
|
92
|
+
@categories.each_value do |category|
|
88
93
|
collection.kinds << category if category.kind_of? OCCI::Core::Kind
|
89
94
|
collection.mixins << category if category.kind_of? OCCI::Core::Mixin
|
90
95
|
collection.actions << category if category.kind_of? OCCI::Core::Action
|
91
96
|
end
|
97
|
+
else
|
98
|
+
categories = filter.categories
|
99
|
+
OCCI::Log.debug("### Filtering categories #{categories.collect { |c| c.type_identifier }.inspect}")
|
100
|
+
while categories.any? do
|
101
|
+
category = categories.pop
|
102
|
+
categories.concat @categories.each_value.select { |cat| cat.related_to?(category.type_identifier, self) }
|
103
|
+
collection.kinds << get_by_id(category.type_identifier) if category.kind_of? OCCI::Core::Kind
|
104
|
+
collection.mixins << get_by_id(category.type_identifier) if category.kind_of? OCCI::Core::Mixin
|
105
|
+
collection.actions << get_by_id(category.type_identifier) if category.kind_of? OCCI::Core::Action
|
106
|
+
end
|
92
107
|
end
|
93
|
-
|
94
|
-
while filter.any? do
|
95
|
-
cat = filter.pop
|
96
|
-
filter.concat @@categories.each_value.select { |category| category.related_to?(cat.type_identifier) }
|
97
|
-
category = get_by_id(cat.type_identifier)
|
98
|
-
collection.kinds << category if category.kind_of?(OCCI::Core::Kind)
|
99
|
-
collection.mixins << category if category.kind_of?(OCCI::Core::Mixin)
|
100
|
-
collection.actions << category if category.kind_of?(OCCI::Core::Action)
|
101
|
-
end
|
102
|
-
return collection
|
108
|
+
collection
|
103
109
|
end
|
104
110
|
|
105
111
|
end
|