cts-mpx-aci 2.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +64 -0
- data/Gemfile +30 -0
- data/Gemfile.lock +178 -0
- data/Guardfile +40 -0
- data/LICENSE +201 -0
- data/README.md +203 -0
- data/Rakefile +6 -0
- data/Rules +53 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/content/CHANGELOG.md +1 -0
- data/content/EXAMPLES.md +1 -0
- data/content/README.md +1 -0
- data/content/assets/bootstrap.min.css +12 -0
- data/content/assets/images/cts-logo-wide.svg +121 -0
- data/content/assets/images/cts-logo.svg +119 -0
- data/content/assets/syntax.css +210 -0
- data/content/coverage +1 -0
- data/content/doc +1 -0
- data/content/specifications.html +1 -0
- data/content/stylesheet.css +101 -0
- data/cts-mpx-aci.gemspec +23 -0
- data/data/stencils/account_record.json +431 -0
- data/data/stencils/media_custom_fields.json +37 -0
- data/data/stencils/servers.json +31 -0
- data/data/stencils/task_templates.json +17 -0
- data/data/stencils/test.json +13 -0
- data/examples/collect.md +21 -0
- data/examples/complete_basic.md +95 -0
- data/examples/deploy.md +25 -0
- data/examples/image.md +41 -0
- data/examples/pre_post_block.md +101 -0
- data/layouts/default.html +52 -0
- data/lib/cts/mpx/aci/extensions/cts/mpx/entries.rb +29 -0
- data/lib/cts/mpx/aci/extensions/cts/mpx/entry.rb +130 -0
- data/lib/cts/mpx/aci/extensions/services/data/entry.rb +136 -0
- data/lib/cts/mpx/aci/stencil.rb +148 -0
- data/lib/cts/mpx/aci/tasks/collect.rb +91 -0
- data/lib/cts/mpx/aci/tasks/deploy.rb +117 -0
- data/lib/cts/mpx/aci/tasks/image.rb +161 -0
- data/lib/cts/mpx/aci/transformations.rb +144 -0
- data/lib/cts/mpx/aci/validators.rb +114 -0
- data/lib/cts/mpx/aci/version.rb +7 -0
- data/lib/cts/mpx/aci.rb +76 -0
- data/nanoc.yaml +22 -0
- metadata +158 -0
@@ -0,0 +1,117 @@
|
|
1
|
+
module Cts
|
2
|
+
module Mpx
|
3
|
+
module Aci
|
4
|
+
module Tasks
|
5
|
+
# Responsible for deploying an image to an account.
|
6
|
+
# @!attribute [rw] user
|
7
|
+
# @return [User] user to make data service calls with
|
8
|
+
# @!attribute [rw] account
|
9
|
+
# @return [String] relative account or nil when untransformed
|
10
|
+
# @!attribute [rw] image
|
11
|
+
# @return [Cts::Mpx::Aci::Tasks::Image]Image containing entries to deploy
|
12
|
+
class Deploy
|
13
|
+
include Creatable
|
14
|
+
|
15
|
+
attribute name: 'account', kind_of: String
|
16
|
+
attribute name: 'image', kind_of: Tasks::Image
|
17
|
+
attribute name: 'user', kind_of: User
|
18
|
+
attribute name: 'pre_block', kind_of: Proc
|
19
|
+
attribute name: 'post_block', kind_of: Proc
|
20
|
+
|
21
|
+
# Any dependencies the image may contain
|
22
|
+
# @return [Hash] dependency hash keyed by entry
|
23
|
+
def dependencies
|
24
|
+
hash = {}
|
25
|
+
image.entries.each do |e|
|
26
|
+
deps = e.dependencies
|
27
|
+
hash.store e.id, deps if deps.any?
|
28
|
+
end
|
29
|
+
hash
|
30
|
+
end
|
31
|
+
|
32
|
+
# rubocop:disable Metrics/AbcSize
|
33
|
+
# reason: these classes is as thin as it can get. not splitting it up to satisify rubocop.
|
34
|
+
# deploy a transformed image to an account
|
35
|
+
# @param [String] target_account to deploy to
|
36
|
+
# @raise [RuntimeError] when image is not deployable
|
37
|
+
def deploy(target_account, *args)
|
38
|
+
raise "not a deployable image" unless Validators.image_deployable? image
|
39
|
+
raise "not a deployable image" unless deploy_order
|
40
|
+
|
41
|
+
deploy_order.each do |ref|
|
42
|
+
entry = image.entries.find { |e| e.id == ref }
|
43
|
+
entry = block_update_entry entry, *args, &pre_block if pre_block
|
44
|
+
|
45
|
+
query = Query.create service: entry.service, endpoint: entry.endpoint, fields: 'id,guid'
|
46
|
+
query.query['byOwnerId'] = target_account
|
47
|
+
|
48
|
+
if entry.id.include? 'Field/'
|
49
|
+
query.query['byQualifiedFieldName'] = "#{entry.fields['namespace']}$#{entry.fields['fieldName']}"
|
50
|
+
else
|
51
|
+
query.query['byGuid'] = entry.fields['guid']
|
52
|
+
end
|
53
|
+
|
54
|
+
if entry.exists_by? user, query
|
55
|
+
method = 'PUT'
|
56
|
+
response = query.run(user: user)
|
57
|
+
entry.id = response.page.entries.first["id"]
|
58
|
+
else
|
59
|
+
entry.id = nil
|
60
|
+
entry.service = query.service
|
61
|
+
entry.endpoint = query.endpoint
|
62
|
+
method = 'POST'
|
63
|
+
end
|
64
|
+
|
65
|
+
entry.fields['ownerId'] = target_account
|
66
|
+
entry.save user: user
|
67
|
+
block_update_entry entry, *args, &post_block if post_block
|
68
|
+
|
69
|
+
logger.info "deployed #{entry.fields['guid']} to #{target_account} as #{entry.id || 'new_id'} with #{user.username} via a #{method} call"
|
70
|
+
end
|
71
|
+
|
72
|
+
true
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Array] order to deploy objects in
|
76
|
+
# @return [nil] if image state is transformed.
|
77
|
+
# @return [nil] if a deploy order could not be generated.
|
78
|
+
def deploy_order
|
79
|
+
return nil unless image.state == :untransformed
|
80
|
+
|
81
|
+
hash = dependencies
|
82
|
+
list = image.entries.map(&:id) - dependencies.keys
|
83
|
+
|
84
|
+
100.times do |_i|
|
85
|
+
break unless hash.any?
|
86
|
+
|
87
|
+
hash.delete_if { |k, _v| list.include? k }
|
88
|
+
|
89
|
+
new_hash = hash.select { |_k, v| (v - list).empty? }
|
90
|
+
list += new_hash.keys if new_hash.any?
|
91
|
+
end
|
92
|
+
|
93
|
+
return list.uniq if image.entries.map(&:id).count == list.count
|
94
|
+
|
95
|
+
nil
|
96
|
+
end
|
97
|
+
# rubocop:enable Metrics/AbcSize
|
98
|
+
|
99
|
+
def block_update_entry(entry, *args, &block)
|
100
|
+
raise ArgumentError, 'block must be provided' unless block
|
101
|
+
raise ArgumentError, 'argument must be an entry' unless entry.is_a? Entry
|
102
|
+
|
103
|
+
e = entry.dup
|
104
|
+
block.yield e, args
|
105
|
+
e
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def logger
|
111
|
+
Aci.logger
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
module Cts
|
2
|
+
module Mpx
|
3
|
+
module Aci
|
4
|
+
module Tasks
|
5
|
+
# Image class for gathering a set of service data as a single collection.
|
6
|
+
#
|
7
|
+
# @!attribute [rw] entries
|
8
|
+
# @return [Hash] set of entries to generate the image from
|
9
|
+
# @!attribute [rw] schema
|
10
|
+
# @return [String] schema of the image
|
11
|
+
# @!attribute [rw] user
|
12
|
+
# @return [User] user to make data service calls with
|
13
|
+
# @!attribute [r] account_id
|
14
|
+
# @return [String] relative account_id or nil when untransformed
|
15
|
+
# @!attribute [r] date_taken
|
16
|
+
# @return [DateTime] Date the image was instantiated
|
17
|
+
# @!attribute [r] state
|
18
|
+
# @return [String] :transformed or :untransformed
|
19
|
+
class Image
|
20
|
+
include Creatable
|
21
|
+
|
22
|
+
attribute name: 'entries', kind_of: Entries
|
23
|
+
attribute name: 'schema', kind_of: Integer
|
24
|
+
attribute name: 'user', kind_of: User
|
25
|
+
attribute name: 'account_id', kind_of: String
|
26
|
+
attribute name: 'date_taken', kind_of: Time
|
27
|
+
attribute name: 'state', kind_of: String
|
28
|
+
|
29
|
+
# load an image from directory
|
30
|
+
#
|
31
|
+
# @param user [String] user to set the image and entries to
|
32
|
+
# @return [Cts::Mpx::aciTasks::Image] image with entries loaded and info set.
|
33
|
+
def self.load_from_directory(directory, user = nil)
|
34
|
+
i = new
|
35
|
+
i.load_from_directory directory, user
|
36
|
+
i
|
37
|
+
end
|
38
|
+
|
39
|
+
# All entries in the entries, including the md5 hash of the data.
|
40
|
+
#
|
41
|
+
# @return [Hash] filepath is key, value is md5
|
42
|
+
def files
|
43
|
+
entries.map(&:filepath)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Generate information report for the image.
|
47
|
+
#
|
48
|
+
# @return [Hash] contains the information about the image.
|
49
|
+
def info
|
50
|
+
{
|
51
|
+
account_id: @account_id,
|
52
|
+
date_taken: @date_taken.iso8601,
|
53
|
+
username: @user.nil? ? "" : @user.username,
|
54
|
+
schema: @schema,
|
55
|
+
state: @state,
|
56
|
+
files: files
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def initialize
|
61
|
+
@account_id = ""
|
62
|
+
@entries = Entries.new
|
63
|
+
@date_taken = Time.now
|
64
|
+
@files = {}
|
65
|
+
@state = :untransformed
|
66
|
+
@schema = 1
|
67
|
+
@user = nil
|
68
|
+
end
|
69
|
+
|
70
|
+
# save an image to a directory
|
71
|
+
#
|
72
|
+
# @param directory [String] the name of the directory to save to
|
73
|
+
def save_to_directory(directory)
|
74
|
+
entries.each do |entry|
|
75
|
+
FileUtils.mkdir_p "#{directory}/#{entry.directory}"
|
76
|
+
File.write "#{directory}/#{entry.filepath}", entry.to_s
|
77
|
+
end
|
78
|
+
|
79
|
+
File.write "#{directory}/info.json", Oj.dump(info, indent: 2)
|
80
|
+
true
|
81
|
+
end
|
82
|
+
|
83
|
+
# load an image from directory
|
84
|
+
#
|
85
|
+
# @param user [String] user to set the image and entries to
|
86
|
+
# @return [Cts::Mpx::Aci::Tasks::Image] image with entries loaded and info set.
|
87
|
+
def load_from_directory(directory, user = nil)
|
88
|
+
raise "#{directory} does not contain a valid image." unless Validators.image_directory? directory
|
89
|
+
|
90
|
+
info = load_json_or_error "#{directory}/info.json"
|
91
|
+
|
92
|
+
["date_taken", "account_id", "schema", "username", "state"].each do |param|
|
93
|
+
instance_variable_set "@#{param}", info[param]
|
94
|
+
end
|
95
|
+
|
96
|
+
entries = Entries.new
|
97
|
+
|
98
|
+
info["files"].each do |file|
|
99
|
+
begin
|
100
|
+
h = load_json_or_error("#{directory}/#{file}")
|
101
|
+
rescue Oj::ParseError
|
102
|
+
raise "#{directory}/#{file} is readable, but not parsable. Please run the json through a linter."
|
103
|
+
end
|
104
|
+
|
105
|
+
entries.add Entry.create(fields: Fields.create_from_data(data: h[:entry], xmlns: h[:xmlns]))
|
106
|
+
end
|
107
|
+
|
108
|
+
@user = user
|
109
|
+
|
110
|
+
true
|
111
|
+
end
|
112
|
+
|
113
|
+
# merge two images together
|
114
|
+
#
|
115
|
+
# @param other_image [Image] Image to merge from
|
116
|
+
# @return [Cts::Mpx::Aci::Tasks::Image] new image containg merged results.
|
117
|
+
def merge(other_image)
|
118
|
+
raise 'an image class must be supplied' unless other_image.is_a? Image
|
119
|
+
raise 'cannot merge if the user is different' unless other_image.user == user
|
120
|
+
raise 'cannot merge if the account_id is different' unless other_image.account_id == account_id
|
121
|
+
raise 'cannot merge if the state is different' unless other_image.state == state
|
122
|
+
|
123
|
+
new_image = Image.new
|
124
|
+
new_image.user = @user
|
125
|
+
new_image.entries = entries + other_image.entries
|
126
|
+
new_image
|
127
|
+
end
|
128
|
+
|
129
|
+
# transform an image to an abstract state
|
130
|
+
def transform
|
131
|
+
entries.each { |entry| entry.transform user }
|
132
|
+
@state = :transformed
|
133
|
+
@account_id = nil
|
134
|
+
true
|
135
|
+
end
|
136
|
+
|
137
|
+
# untransform an image from an abstract state
|
138
|
+
# @param target_account [String] account_id to transform to
|
139
|
+
def untransform(target_account)
|
140
|
+
entries.each do |entry|
|
141
|
+
entry.fields['ownerId'] = target_account
|
142
|
+
entry.untransform user, target_account
|
143
|
+
end
|
144
|
+
|
145
|
+
@state = :untransformed
|
146
|
+
@account_id = target_account
|
147
|
+
true
|
148
|
+
end
|
149
|
+
|
150
|
+
private
|
151
|
+
|
152
|
+
def load_json_or_error(file)
|
153
|
+
Oj.load File.read file
|
154
|
+
rescue Oj::ParseError => exception
|
155
|
+
raise "#{exception.message.split(' [').first}: #{file}"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
module Cts
|
2
|
+
module Mpx
|
3
|
+
module Aci
|
4
|
+
# contains the logic to transform/untransform an entry.
|
5
|
+
module Transformations
|
6
|
+
module_function
|
7
|
+
|
8
|
+
# Transform a reference into a transformed_reference
|
9
|
+
# @param [User] user that will make the service calls.
|
10
|
+
# @param [String] original_account to do the transformation from
|
11
|
+
# @param [String] reference to transform to a transformed reference
|
12
|
+
# @return [String] transformed_reference
|
13
|
+
def transform_reference(reference: nil, user: nil, original_account: nil)
|
14
|
+
return "urn:cts:aci:target-account" if reference == original_account
|
15
|
+
return reference unless Validators.reference? reference
|
16
|
+
|
17
|
+
service_info = Services.from_url reference
|
18
|
+
endpoint = service_info[:endpoint]
|
19
|
+
service = service_info[:service]
|
20
|
+
return reference if service.start_with? "User Data Service"
|
21
|
+
|
22
|
+
response = Services::Data.get user: user, service: service, endpoint: endpoint, ids: reference.split('/').last
|
23
|
+
|
24
|
+
return "urn:cts:aci:no-id-found" unless (entry = response.data["entries"].first)
|
25
|
+
|
26
|
+
return "urn:cts:aci:no-guid-found" unless (guid = entry["guid"])
|
27
|
+
|
28
|
+
"urn:cts:aci:#{URI.encode_www_form_component(service)}:#{endpoint}:#{entry['ownerId'].split('/').last}:#{guid}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Transform a field reference into a transformed_field_reference
|
32
|
+
# @param [User] user that will make the service calls.
|
33
|
+
# @param [String] field_reference to transform to a transformed field reference
|
34
|
+
# @return [String] transformed_field_reference
|
35
|
+
def transform_field_reference(field_reference: nil, user: nil)
|
36
|
+
return field_reference unless Validators.field_reference? field_reference
|
37
|
+
|
38
|
+
service_info = Services.from_url field_reference
|
39
|
+
endpoint = service_info[:endpoint]
|
40
|
+
service = service_info[:service]
|
41
|
+
response = Services::Data.get user: user, service: service, endpoint: endpoint, ids: field_reference.split('/').last, fields: 'ownerId,fieldName,namespace'
|
42
|
+
return "urn:cts:aci:no-id-found" unless (entry = response.data["entries"].first)
|
43
|
+
return "urn:cts:aci:no-qualified-field-name-found" unless entry["fieldName"]
|
44
|
+
|
45
|
+
namespace = response.data['namespace']
|
46
|
+
owner_id = entry['ownerId'].split('/').last
|
47
|
+
"urn:cts:aci:#{URI.encode_www_form_component(service)}:#{endpoint}:#{owner_id}:#{namespace}$#{entry['fieldName']}"
|
48
|
+
end
|
49
|
+
|
50
|
+
# Untransform a transformed_reference into a reference
|
51
|
+
# @param [User] user that will make the service calls.
|
52
|
+
# @param [String] target_account to do the transformation from
|
53
|
+
# @param [String] transformed_reference to transform to a reference
|
54
|
+
# @return [String] reference
|
55
|
+
def untransform_reference(transformed_reference: nil, user: nil, target_account: nil)
|
56
|
+
return target_account if transformed_reference == "urn:cts:aci:target-account"
|
57
|
+
return transformed_reference unless Validators.transformed_reference? transformed_reference
|
58
|
+
|
59
|
+
parts = transformed_reference.split ':'
|
60
|
+
endpoint = parts[4]
|
61
|
+
service = parts[3]
|
62
|
+
guid = URI.decode_www_form_component(parts[6])
|
63
|
+
owner_id = "http://access.auth.theplatform.com/data/Account/#{parts[5]}"
|
64
|
+
|
65
|
+
response = Services::Data.get user: user,
|
66
|
+
service: service,
|
67
|
+
endpoint: endpoint,
|
68
|
+
ids: transformed_reference.split('/').last,
|
69
|
+
query: { byGuid: guid, ownerId: owner_id }
|
70
|
+
|
71
|
+
raise "could not find an entry by guid" unless (entry = response.data["entries"].first)
|
72
|
+
raise "service returned too many entries on guid" if response.data["entries"].count > 1
|
73
|
+
|
74
|
+
entry['id']
|
75
|
+
end
|
76
|
+
|
77
|
+
# Untransform a transformed_field_reference into a field reference
|
78
|
+
# @param [User] user that will make the service calls.
|
79
|
+
# @param [String] transformed_field_reference to transform to a reference
|
80
|
+
# @return [String] field_reference
|
81
|
+
def untransform_field_reference(transformed_field_reference: nil, user: nil, target_account: nil)
|
82
|
+
return transformed_field_reference unless Validators.transformed_field_reference? transformed_field_reference
|
83
|
+
|
84
|
+
parts = transformed_field_reference.split ':'
|
85
|
+
endpoint = parts[4]
|
86
|
+
service = parts[3]
|
87
|
+
qualified_field_name = URI.decode_www_form_component(parts[6])
|
88
|
+
owner_id = "http://access.auth.theplatform.com/data/Account/#{parts[5]}"
|
89
|
+
|
90
|
+
response = Services::Data.get user: user,
|
91
|
+
service: service,
|
92
|
+
endpoint: endpoint,
|
93
|
+
query: { byQualifiedFieldName: qualified_field_name, ownerId: owner_id }
|
94
|
+
|
95
|
+
raise "could not find an entry by qualified field name" unless (entry = response.data["entries"].first)
|
96
|
+
raise "service returned too many entries on qualified field name" if response.data["entries"].count > 1
|
97
|
+
|
98
|
+
entry['id']
|
99
|
+
end
|
100
|
+
|
101
|
+
def traverse_for(hash, direction, &block)
|
102
|
+
id = hash['id']
|
103
|
+
output = hash.reject { |k, _v| k == 'id' }
|
104
|
+
output = Transformations.send :traverse_hash, Oj.load(Oj.dump(output)), direction, &block
|
105
|
+
{ "id" => id }.merge(output)
|
106
|
+
end
|
107
|
+
|
108
|
+
# private module method, not explicitly covered
|
109
|
+
def traverse_hash(entry, direction, &block)
|
110
|
+
entry.each do |field, value|
|
111
|
+
case value
|
112
|
+
when String
|
113
|
+
entry[field] = block.yield field, value if direction == :transform &&
|
114
|
+
Validators.reference?(value)
|
115
|
+
entry[field] = block.yield field, value if direction == :untransform &&
|
116
|
+
Validators.transformed_reference?(value)
|
117
|
+
when Array
|
118
|
+
entry[field] = traverse_array field, value, direction, &block
|
119
|
+
when Hash
|
120
|
+
entry[field] = traverse_hash value, direction, &block
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# private module method, not explicitly covered
|
126
|
+
def traverse_array(field, value, direction, &block)
|
127
|
+
if value.map(&:class).uniq.first == String
|
128
|
+
value.map do |v|
|
129
|
+
if Validators.reference?(v) || Validators.transformed_reference?(v)
|
130
|
+
block.yield field, v
|
131
|
+
else
|
132
|
+
v
|
133
|
+
end
|
134
|
+
end
|
135
|
+
elsif value.map(&:class).uniq.first == Hash
|
136
|
+
value.map { |v| traverse_hash v, direction, &block }
|
137
|
+
else
|
138
|
+
value
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Cts
|
2
|
+
module Mpx
|
3
|
+
module Aci
|
4
|
+
# Wireline Validators
|
5
|
+
module Validators
|
6
|
+
module_function
|
7
|
+
|
8
|
+
# Test if a string is a reference or not
|
9
|
+
# @param [String] uri to test if it is a reference or not
|
10
|
+
# @return [Boolean]
|
11
|
+
def reference?(uri)
|
12
|
+
Cts::Mpx::Validators.reference?(uri)
|
13
|
+
end
|
14
|
+
|
15
|
+
def field_reference?(uri)
|
16
|
+
begin
|
17
|
+
ref = URI.parse uri
|
18
|
+
rescue URI::InvalidURIError
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
return false if ref.host == 'web.theplatform.com'
|
23
|
+
return false unless ref.scheme == "http" || ref.scheme == "https"
|
24
|
+
return false unless ref.host.end_with? ".theplatform.com"
|
25
|
+
return false unless ref.path =~ /Field\/\d+/
|
26
|
+
return false if ref.path =~ /\/\D+$/
|
27
|
+
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
# Test if a string is a transformed_reference or not
|
32
|
+
# @param [String] string to check if it is a transformed_reference
|
33
|
+
# @return [Boolean]
|
34
|
+
def transformed_reference?(string)
|
35
|
+
return true if [
|
36
|
+
'urn:cts:aci:target-account',
|
37
|
+
'urn:cts:aci:no-id-found',
|
38
|
+
'urn:cts:aci:no-guid-found',
|
39
|
+
'urn:cts:aci:no-custom-field-found'
|
40
|
+
].include? string
|
41
|
+
|
42
|
+
urn_regex = /^(?i:urn:(?!urn:)([cC][tT][sS]):(?<nss>(?:[a-z0-9()\/+,-.:=@;$_!*']|%[0-9a-f]{2})+))$/
|
43
|
+
|
44
|
+
return false unless urn_regex =~ string
|
45
|
+
|
46
|
+
nss = urn_regex.match(string)["nss"]
|
47
|
+
segments = nss.split(":")
|
48
|
+
|
49
|
+
return false unless /^([aA][cC][iI])$/ =~ segments[0]
|
50
|
+
|
51
|
+
begin
|
52
|
+
service = Services[URI.decode_www_form_component(segments[1])]
|
53
|
+
rescue RuntimeError
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
|
57
|
+
return false unless service.endpoints.include? segments[2].gsub('Field', '/Field')
|
58
|
+
return false unless /\A\d+\z/ =~ segments[3]
|
59
|
+
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
# Test if a string is a transformed_field_reference or not
|
64
|
+
# @param [String] string to check if it is a transformed_field_reference
|
65
|
+
# @return [Boolean]
|
66
|
+
def transformed_field_reference?(string)
|
67
|
+
return false unless transformed_reference? string
|
68
|
+
return false unless /Field:\d*:.*$/.match? string
|
69
|
+
|
70
|
+
true
|
71
|
+
end
|
72
|
+
|
73
|
+
# test if a directory is an image_directory
|
74
|
+
# @param [String] image_directory to check if it is a transformed_reference
|
75
|
+
# @return [Boolean]
|
76
|
+
def image_directory?(image_directory)
|
77
|
+
return false unless File.exist? "#{image_directory}/info.json"
|
78
|
+
|
79
|
+
true
|
80
|
+
end
|
81
|
+
|
82
|
+
# test if a image will depoly
|
83
|
+
# @param [Tasks::Image] image to check if it is a transformed_reference
|
84
|
+
# @return [Boolean]
|
85
|
+
def image_deployable?(image)
|
86
|
+
return false if image.state == :transformed || image.state == 'transformed'
|
87
|
+
return false if image.entries.collection.empty?
|
88
|
+
|
89
|
+
image.entries.each do |entry|
|
90
|
+
Transformations.traverse_for(entry.to_h, :untransform) do |_k, v|
|
91
|
+
return false if v =~ /^urn:cts:aci:no-(gu)?id-found$/
|
92
|
+
end
|
93
|
+
end
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
97
|
+
# Test if a string is a transformed_reference or not
|
98
|
+
# @param [String] filename to check if it is a valid info.json or not
|
99
|
+
# @return [Boolean]
|
100
|
+
def info_file?(filename)
|
101
|
+
raise "could not find an info.json" unless File.exist? filename
|
102
|
+
|
103
|
+
begin
|
104
|
+
Oj.load(File.read(filename))
|
105
|
+
rescue Oj::ParseError
|
106
|
+
return false
|
107
|
+
end
|
108
|
+
|
109
|
+
true
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|