Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
slapos
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
104
Merge Requests
104
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
nexedi
slapos
Commits
d26d1810
Commit
d26d1810
authored
Jan 10, 2025
by
Xavier Thompson
Browse files
Options
Browse Files
Download
Plain Diff
Introduce slapconfiguration:jsonschema recipe
See merge request
!1638
parents
93374140
c0306e8b
Pipeline
#38975
failed with stage
in 0 seconds
Changes
3
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
614 additions
and
16 deletions
+614
-16
setup.py
setup.py
+1
-0
slapos/recipe/slapconfiguration.py
slapos/recipe/slapconfiguration.py
+218
-12
slapos/test/recipe/test_slaposconfiguration.py
slapos/test/recipe/test_slaposconfiguration.py
+395
-4
No files found.
setup.py
View file @
d26d1810
...
...
@@ -150,6 +150,7 @@ setup(name=name,
'simplehttpserver = slapos.recipe.simplehttpserver:Recipe'
,
'slapconfiguration = slapos.recipe.slapconfiguration:Recipe'
,
'slapconfiguration.serialised = slapos.recipe.slapconfiguration:Serialised'
,
'slapconfiguration.jsonschema = slapos.recipe.slapconfiguration:JsonSchema'
,
'slapconfiguration.jsondump = slapos.recipe.slapconfiguration:JsonDump'
,
'squid = slapos.recipe.squid:Recipe'
,
'sshkeys_authority = slapos.recipe.sshkeys_authority:Recipe'
,
...
...
slapos/recipe/slapconfiguration.py
View file @
d26d1810
...
...
@@ -29,13 +29,24 @@ import json
import
logging
import
os
from
collections
import
defaultdict
from
contextlib
import
contextmanager
import
jsonschema
import
slapos.slap
from
slapos.recipe.librecipe
import
unwrap
import
six
from
six.moves.configparser
import
RawConfigParser
from
netaddr
import
valid_ipv4
,
valid_ipv6
from
slapos.util
import
mkdir_p
from
slapos.util
import
(
mkdir_p
,
SoftwareReleaseSchema
,
SoftwareReleaseSerialisation
,
SoftwareReleaseSchemaValidationError
,
urljoin
,
)
from
slapos
import
format
as
slapformat
from
zc.buildout
import
UserError
logger
=
logging
.
getLogger
(
"slapos"
)
...
...
@@ -52,21 +63,21 @@ class Recipe(object):
For example {"tun": {"ipv4": <addr>}} would be available in buildout as ${instance:tun-ipv4}.
Input:
url
url
| server-url
Slap server url.
Example:
${slap-connection:server-url}
key & cert (optional)
key & cert
| key-file & cert-file
(optional)
Path of files containing key and certificate for secure connection to
slap server.
Example:
${slap-connection:key-file}
${slap-connection:cert-file}
computer
computer
| computer-id
Computer identifier.
Example:
${slap-connection:computer-id}
partition
partition
| partition-id
Partition identifier.
Example:
${slap-connection:partition-id}
...
...
@@ -129,14 +140,16 @@ class Recipe(object):
2. format.Partition.resource_file - for partition specific details
"""
slap
=
slapos
.
slap
.
slap
()
# BBB: or ... (right side) clauses kept for compatibility;
# left-side clauses correspond directly to slap-connection.
slap
.
initializeConnection
(
options
[
'url'
],
options
.
get
(
'key'
),
options
.
get
(
'cert'
),
options
.
get
(
'server-url'
)
or
options
[
'url'
],
options
.
get
(
'key
-file'
)
or
options
.
get
(
'key
'
),
options
.
get
(
'cert
-file'
)
or
options
.
get
(
'cert
'
),
)
computer_partition
=
slap
.
registerComputerPartition
(
options
[
'computer'
],
options
[
'partition'
],
options
.
get
(
'computer-id'
)
or
options
[
'computer'
],
options
.
get
(
'partition-id'
)
or
options
[
'partition'
],
)
parameter_dict
=
computer_partition
.
getInstanceParameterDict
()
options
[
'instance-state'
]
=
computer_partition
.
getState
()
...
...
@@ -162,7 +175,6 @@ class Recipe(object):
options
[
'root-instance-title'
]
=
parameter_dict
.
pop
(
'root_instance_title'
,
'UNKNOWN'
)
options
[
'instance-guid'
]
=
computer_partition
.
getInstanceGuid
()
ipv4_set
=
set
()
v4_add
=
ipv4_set
.
add
ipv6_set
=
set
()
...
...
@@ -185,6 +197,10 @@ class Recipe(object):
v6_add
(
ip
)
# XXX: emit warning on unknown address type ?
# XXX slapproxy is sending 'full_address_list' not 'full_ip_list' (like real slapos master)
# just pop this value for now. Remove this when slapproxy is fixed.
parameter_dict
.
pop
(
'full_address_list'
,
None
)
if
'full_ip_list'
in
parameter_dict
:
for
item
in
parameter_dict
.
pop
(
'full_ip_list'
):
if
len
(
item
)
==
5
:
...
...
@@ -199,6 +215,11 @@ class Recipe(object):
if
valid_ipv4
(
network
):
route_net_add
(
network
)
# validate the parameters (only when using JsonSchema recipe)
# after popping the custom values sent by slapos master
# but before adding the value from .slapos-resources file
parameter_dict
=
self
.
_validateParameterDict
(
options
,
parameter_dict
)
options
[
'ipv4'
]
=
ipv4_set
options
[
'ipv6'
]
=
ipv6_set
...
...
@@ -247,6 +268,9 @@ class Recipe(object):
logger
.
debug
(
str
(
options
))
return
self
.
_expandParameterDict
(
options
,
parameter_dict
)
def
_validateParameterDict
(
self
,
options
,
parameter_dict
):
return
parameter_dict
def
_expandParameterDict
(
self
,
options
,
parameter_dict
):
options
[
'configuration'
]
=
parameter_dict
return
parameter_dict
...
...
@@ -261,6 +285,188 @@ class Serialised(Recipe):
else
:
return
{}
class
BasicValidator
(
object
):
def
__init__
(
self
,
schema
):
self
.
schema
=
schema
self
.
validator
=
jsonschema
.
validators
.
validator_for
(
schema
)(
schema
)
def
validate
(
self
,
instance
):
for
error
in
self
.
validator
.
iter_errors
(
instance
):
yield
error
class
DefaultValidator
(
object
):
def
__init__
(
self
,
schema
):
self
.
schema
=
schema
self
.
validatorfor
=
v
=
jsonschema
.
validators
.
validator_for
(
schema
)
# Retain original properties validator
validate_properties
=
v
.
VALIDATORS
[
"properties"
]
# Define new properties validator
def
collect_defaults
(
validator
,
properties
,
instance
,
schema
):
# Call original properties validator
error
=
False
for
e
in
validate_properties
(
validator
,
properties
,
instance
,
schema
):
error
=
True
yield
e
# Collect defaults if the instance validates this schema
if
not
error
:
for
key
,
subschema
in
properties
.
items
():
if
"default"
in
subschema
:
try
:
_
,
defaults
=
self
.
defaults
[
id
(
instance
)]
except
KeyError
:
defaults
=
defaultdict
(
dict
)
self
.
defaults
[
id
(
instance
)]
=
instance
,
defaults
defaults
[
key
][
id
(
subschema
)]
=
subschema
[
"default"
]
# Extend validator class with extended properties validator
kls
=
jsonschema
.
validators
.
extend
(
v
,
{
"properties"
:
collect_defaults
})
self
.
validator
=
kls
(
schema
)
@
contextmanager
def
propagate
(
self
):
# Workaround https://github.com/python-jsonschema/jsonschema/issues/994
# This only works if all $ref schemas have the same $schema as the first.
version
=
self
.
schema
.
get
(
"$schema"
)
try
:
if
version
is
not
None
:
jsonschema
.
validators
.
validates
(
version
)(
type
(
self
.
validator
))
yield
finally
:
if
version
is
not
None
:
jsonschema
.
validators
.
validates
(
version
)(
self
.
validatorfor
)
def
validate
(
self
,
instance
):
# Initialise default collection
self
.
defaults
=
{}
# Validate instance
invalid
=
False
with
self
.
propagate
():
for
error
in
self
.
validator
.
iter_errors
(
instance
):
invalid
=
True
yield
error
# Stop there in case of validation errors
if
invalid
:
return
# Apply collected defaults
for
data
,
defaults
in
self
.
defaults
.
values
():
for
key
,
defaultdict
in
defaults
.
items
():
if
key
not
in
data
:
it
=
iter
(
defaultdict
.
values
())
default
=
next
(
it
)
if
any
(
d
!=
default
for
d
in
it
):
raise
UserError
(
"Conflicting defaults for key %s: %r"
%
(
key
,
defaultlist
))
data
[
key
]
=
default
# Validate the updated instance
for
error
in
self
.
validatorfor
(
self
.
schema
).
iter_errors
(
instance
):
yield
error
class
JsonSchema
(
Recipe
):
"""
Input:
jsonschema
JSON Schema for the SR.
All instance schemas must be available at the advertised relative paths.
Example:
${buildout:directory}/software.cfg.json
set-default
Enum to control adding defaults specified by the JSON schema
to both/neither/either-of main and shared instance parameters.
Accepted values: all|main|shared|none.
Default value: none.
Example:
shared
validate-parameters
Enum to control validating instance parameters
for both/neither/either-of main and shared instances.
Accepted values: all|main|shared|none.
Example:
shared
"""
def
_schema
(
self
,
options
):
path
=
options
[
'jsonschema'
]
# because SoftwareReleaseSchema accepts only file:// paths
path
=
path
if
path
.
startswith
(
'file://'
)
else
'file://'
+
path
# because SoftwareReleaseSchema expects the SR url and adds .json
path
=
path
[:
-
5
]
if
path
.
endswith
(
'.json'
)
else
path
return
SoftwareReleaseSchema
(
path
,
options
[
'slap-software-type'
])
def
_getSharedSchema
(
self
,
software_schema
):
t
=
software_schema
.
software_type
software_json_dict
=
software_schema
.
getSoftwareSchema
()
for
type_dict
in
software_json_dict
[
'software-type'
].
values
():
if
type_dict
[
'software-type'
]
==
t
and
type_dict
.
get
(
'shared'
)
==
True
:
url
=
urljoin
(
software_schema
.
software_url
,
type_dict
[
'request'
])
return
software_schema
.
_readAsJson
(
url
,
True
)
def
_parseParameterDict
(
self
,
software_schema
,
parameter_dict
):
instance_schema
=
software_schema
.
getInstanceRequestParameterSchema
()
instance
=
parameter_dict
if
isinstance
(
parameter_dict
,
dict
)
else
{}
validator
=
self
.
Validator
(
instance_schema
)
errors
=
list
(
validator
.
validate
(
instance
))
if
errors
:
err
=
SoftwareReleaseSchemaValidationError
(
errors
).
format_error
(
indent
=
2
)
msg
=
"Invalid parameters:
\
n
"
+
err
raise
UserError
(
msg
)
return
instance
def
_parseSharedParameterDict
(
self
,
software_schema
,
options
):
shared_list
=
options
.
pop
(
'slave-instance-list'
)
if
not
shared_list
:
return
shared_schema
=
self
.
_getSharedSchema
(
software_schema
)
validator
=
self
.
SharedValidator
(
shared_schema
)
valid
,
invalid
=
[],
[]
for
instance
in
shared_list
:
reference
=
instance
.
pop
(
'slave_reference'
)
try
:
errors
=
list
(
validator
.
validate
(
instance
))
except
UserError
as
e
:
errors
=
list
(
e
.
args
)
shared_item
=
{
'reference'
:
reference
,
'parameters'
:
instance
}
if
errors
:
shared_item
[
'errors'
]
=
errors
invalid
.
append
(
shared_item
)
else
:
valid
.
append
(
shared_item
)
options
[
'valid-shared-instance-list'
]
=
valid
options
[
'invalid-shared-instance-list'
]
=
invalid
def
_parseOption
(
self
,
options
,
key
,
default
):
value
=
options
.
get
(
key
,
default
)
accepted
=
(
'none'
,
'main'
,
'shared'
,
'all'
)
try
:
index
=
accepted
.
index
(
value
)
except
ValueError
:
raise
UserError
(
"%r is not a valid value for option %r"
"Accepted values are %r"
%
(
value
,
key
,
accepted
)
)
# return: value in ('main', 'all'), value in ('shared', 'all')
return
index
&
1
,
index
&
2
def
_validateParameterDict
(
self
,
options
,
parameter_dict
):
set_main
,
set_shared
=
self
.
_parseOption
(
options
,
'set-default'
,
'none'
)
validate_tuple
=
self
.
_parseOption
(
options
,
'validate-parameters'
,
'all'
)
validate_main
,
validate_shared
=
validate_tuple
self
.
Validator
=
DefaultValidator
if
set_main
else
BasicValidator
self
.
SharedValidator
=
DefaultValidator
if
set_shared
else
BasicValidator
software_schema
=
self
.
_schema
(
options
)
serialisation
=
software_schema
.
getSerialisation
(
strict
=
True
)
if
serialisation
==
SoftwareReleaseSerialisation
.
JsonInXml
:
parameter_dict
=
unwrap
(
parameter_dict
)
if
validate_shared
:
self
.
_parseSharedParameterDict
(
software_schema
,
options
)
if
validate_main
:
parameter_dict
=
self
.
_parseParameterDict
(
software_schema
,
parameter_dict
)
options
[
'configuration'
]
=
parameter_dict
if
validate_main
or
isinstance
(
parameter_dict
,
dict
):
return
parameter_dict
return
{}
class
JsonDump
(
Recipe
):
def
__init__
(
self
,
buildout
,
name
,
options
):
parameter_dict
=
self
.
fetch_parameter_dict
(
options
)
...
...
slapos/test/recipe/test_slaposconfiguration.py
View file @
d26d1810
# coding: utf-8
import
copy
import
json
import
mock
import
os
import
shutil
import
unittest
import
tempfile
from
collections
import
defaultdict
...
...
@@ -32,17 +34,16 @@ class SlapConfigurationTest(unittest.TestCase):
"directory"
:
self
.
instance_root
}
}
self
.
software_root
=
tempfile
.
mkdtemp
()
def
tearDown
(
self
):
os
.
unlink
(
self
.
resource_file
)
os
.
rmdir
(
self
.
instance_root
)
shutil
.
rmtree
(
self
.
software_root
)
@
mock
.
patch
(
"slapos.slap.slap"
)
def
test_correct_naming
(
self
,
MockClient
):
def
test_correct_naming
(
self
,
_
):
"""Test correct naming of variables from resource file."""
MockClient
.
initializeConnection
.
return_value
=
None
MockClient
.
getInstanceParameterDict
.
return_value
=
dict
()
options
=
defaultdict
(
str
)
recipe
=
slapconfiguration
.
Recipe
(
self
.
buildout
,
"slapconfiguration"
,
options
)
...
...
@@ -52,3 +53,393 @@ class SlapConfigurationTest(unittest.TestCase):
self
.
assertEqual
(
options
[
'address-list'
],
[
10
,
20
],
"All underscores should be replaced with -"
)
def
writeJsonSchema
(
self
,
serialisation
=
'json-in-xml'
,
valid_defaults
=
True
):
self
.
software_json_file
=
os
.
path
.
join
(
self
.
software_root
,
'software.cfg.json'
)
software_schema
=
{
"name"
:
"Test"
,
"serialisation"
:
serialisation
,
"software-type"
:
{
"default"
:
{
"title"
:
"Default"
,
"software-type"
:
"default"
,
"request"
:
"instance-default-input.json"
,
"index"
:
0
,
},
"default/*"
:
{
"title"
:
"Default"
,
"shared"
:
True
,
"software-type"
:
"default"
,
"request"
:
"shared-default-input.json"
,
"index"
:
0
,
},
}
}
with
open
(
self
.
software_json_file
,
'w'
)
as
f
:
json
.
dump
(
software_schema
,
f
)
self
.
instance_json_file
=
os
.
path
.
join
(
self
.
software_root
,
'instance-default-input.json'
)
properties
=
{
"letter"
:
{
"type"
:
"string"
,
"enum"
:
[
"a"
,
"b"
,
"c"
],
"default"
:
"a"
if
valid_defaults
else
1
,
},
"number"
:
{
"type"
:
"integer"
,
},
}
default_dict
=
{}
without_default
=
[]
for
key
,
obj
in
properties
.
items
():
default
=
obj
.
get
(
'default'
)
if
default
is
None
:
without_default
.
append
(
key
)
else
:
default_dict
[
key
]
=
default
self
.
default_dict
=
default_dict
instance_schema
=
{
"$schema"
:
"https://json-schema.org/draft/2019-09/schema"
,
"$defs"
:
{
"instance-parameters"
:
{
"type"
:
"object"
,
"properties"
:
properties
,
"required"
:
without_default
,
},
},
"unevaluatedProperties"
:
False
,
"allOf"
:
[{
"$ref"
:
"#/$defs/instance-parameters"
},]
}
with
open
(
self
.
instance_json_file
,
'w'
)
as
f
:
json
.
dump
(
instance_schema
,
f
)
self
.
shared_json_file
=
os
.
path
.
join
(
self
.
software_root
,
'shared-default-input.json'
)
shared_schema
=
{
"$schema"
:
"https://json-schema.org/draft/2019-09/schema"
,
"type"
:
"object"
,
"oneOf"
:
[
{
"$ref"
:
"shared-1-default-input.json"
},
{
"$ref"
:
"shared-2-default-input.json"
},
]
}
with
open
(
self
.
shared_json_file
,
'w'
)
as
f
:
json
.
dump
(
shared_schema
,
f
)
self
.
shared_1_json_file
=
os
.
path
.
join
(
self
.
software_root
,
'shared-1-default-input.json'
)
shared_1_schema
=
{
"$schema"
:
"https://json-schema.org/draft/2019-09/schema"
,
"type"
:
"object"
,
"properties"
:
{
"kind"
:
{
"const"
:
1
,
},
"thing"
:
{
"type"
:
"string"
,
"default"
:
"hello"
if
valid_defaults
else
1
,
},
},
"required"
:
[
"kind"
],
}
with
open
(
self
.
shared_1_json_file
,
'w'
)
as
f
:
json
.
dump
(
shared_1_schema
,
f
)
self
.
shared_2_json_file
=
os
.
path
.
join
(
self
.
software_root
,
'shared-2-default-input.json'
)
shared_2_schema
=
{
"$schema"
:
"https://json-schema.org/draft/2019-09/schema"
,
"type"
:
"object"
,
"properties"
:
{
"kind"
:
{
"const"
:
2
,
},
"thing"
:
{
"type"
:
"integer"
,
"default"
:
42
if
valid_defaults
else
"forty-two"
,
},
"required"
:
[
"kind"
],
}
}
with
open
(
self
.
shared_2_json_file
,
'w'
)
as
f
:
json
.
dump
(
shared_2_schema
,
f
)
def
patchSlap
(
self
,
parameters
,
serialise
,
shared
=
None
,
software_type
=
'default'
):
shared
=
copy
.
deepcopy
(
shared
)
if
shared
else
[]
d
=
{
'_'
:
json
.
dumps
(
parameters
)}
if
serialise
else
copy
.
deepcopy
(
parameters
)
for
i
,
s
in
enumerate
(
shared
):
s
[
'slave_reference'
]
=
'SHARED%s'
%
i
slap
=
mock
.
MagicMock
()
slap_object
=
slap
.
return_value
slap_object
.
initializeConnection
.
return_value
=
None
computer_partition
=
slap_object
.
registerComputerPartition
.
return_value
computer_partition
.
getInstanceParameterDict
.
return_value
=
d
d
[
'ip_list'
]
=
[]
d
[
'slap_software_type'
]
=
software_type
d
[
'slave_instance_list'
]
=
shared
return
mock
.
patch
(
"slapos.slap.slap"
,
slap
)
def
runJsonSchemaRecipe
(
self
,
options
=
()):
options
=
defaultdict
(
str
,
options
)
options
[
'jsonschema'
]
=
self
.
software_json_file
slapconfiguration
.
JsonSchema
(
self
.
buildout
,
"slapconfiguration"
,
options
)
return
options
def
receiveParameters
(
self
,
options
=
((
'set-default'
,
'all'
),)):
options
=
self
.
runJsonSchemaRecipe
(
options
)
return
options
[
'configuration'
]
def
receiveSharedParameters
(
self
,
options
=
((
'set-default'
,
'all'
),)):
options
=
self
.
runJsonSchemaRecipe
(
options
)
self
.
assertNotIn
(
'slave-instance-list'
,
options
)
valid
=
options
[
'valid-shared-instance-list'
]
invalid
=
options
[
'invalid-shared-instance-list'
]
valid
=
{
d
[
'reference'
]:
d
[
'parameters'
]
for
d
in
valid
}
invalid
=
{
d
[
'reference'
]:
d
[
'parameters'
]
for
d
in
invalid
}
return
valid
,
invalid
def
checkParametersWithDefaults
(
self
,
received_parameters
,
sent_parameters
):
expected_dict
=
dict
(
self
.
default_dict
)
expected_dict
.
update
(
sent_parameters
)
self
.
assertEqual
(
received_parameters
,
expected_dict
)
def
test_jsonschema_json_in_xml_valid_xml_input_defaults
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
with
self
.
patchSlap
(
parameters
,
False
):
received
=
self
.
receiveParameters
()
self
.
checkParametersWithDefaults
(
received
,
parameters
)
def
test_jsonschema_json_in_xml_valid_json_input_defaults
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
with
self
.
patchSlap
(
parameters
,
True
):
received
=
self
.
receiveParameters
()
self
.
checkParametersWithDefaults
(
received
,
parameters
)
def
test_jsonschema_json_in_xml_valid_input_without_defaults
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
with
self
.
patchSlap
(
parameters
,
True
):
received
=
self
.
receiveParameters
(
options
=
())
self
.
assertEqual
(
received
,
parameters
)
def
test_jsonschema_json_in_xml_valid_input_with_only_shared_defaults
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
with
self
.
patchSlap
(
parameters
,
True
):
received
=
self
.
receiveParameters
({
'set-default'
:
'shared'
})
self
.
assertEqual
(
received
,
parameters
)
def
test_jsonschema_json_in_xml_valid_input_with_only_main_defaults
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
with
self
.
patchSlap
(
parameters
,
True
):
received
=
self
.
receiveParameters
({
'set-default'
:
'main'
})
self
.
checkParametersWithDefaults
(
received
,
parameters
)
def
test_jsonschema_json_in_xml_valid_xml_input_full
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"letter"
:
"b"
,
"number"
:
1
}
with
self
.
patchSlap
(
parameters
,
False
):
received
=
self
.
receiveParameters
()
self
.
checkParametersWithDefaults
(
received
,
parameters
)
def
test_jsonschema_json_in_xml_valid_json_input_full
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"letter"
:
"b"
,
"number"
:
1
}
with
self
.
patchSlap
(
parameters
,
True
):
received
=
self
.
receiveParameters
()
self
.
checkParametersWithDefaults
(
received
,
parameters
)
def
test_jsonschema_json_in_xml_wrong_type_xml_input
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
"1"
}
with
self
.
patchSlap
(
parameters
,
False
):
self
.
assertRaises
(
slapconfiguration
.
UserError
,
self
.
receiveParameters
,
)
def
test_jsonschema_json_in_xml_wrong_type_json_input
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
"1"
}
with
self
.
patchSlap
(
parameters
,
True
):
self
.
assertRaises
(
slapconfiguration
.
UserError
,
self
.
receiveParameters
,
)
def
test_jsonschema_json_in_xml_wrong_type_json_input_skip_main
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
"1"
}
with
self
.
patchSlap
(
parameters
,
True
):
received
=
self
.
receiveParameters
({
'validate-parameters'
:
'shared'
})
self
.
assertEqual
(
received
,
parameters
)
def
test_jsonschema_json_in_xml_wrong_type_json_input_skip_shared
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
"1"
}
with
self
.
patchSlap
(
parameters
,
True
):
self
.
assertRaises
(
slapconfiguration
.
UserError
,
self
.
receiveParameters
,
{
'validate-parameters'
:
'main'
},
)
def
test_jsonschema_json_in_xml_incomplete_xml_input
(
self
):
self
.
writeJsonSchema
()
parameters
=
{}
with
self
.
patchSlap
(
parameters
,
False
):
self
.
assertRaises
(
slapconfiguration
.
UserError
,
self
.
receiveParameters
,
)
def
test_jsonschema_json_in_xml_incomplete_json_input
(
self
):
self
.
writeJsonSchema
()
parameters
=
{}
with
self
.
patchSlap
(
parameters
,
True
):
self
.
assertRaises
(
slapconfiguration
.
UserError
,
self
.
receiveParameters
,
)
def
test_jsonschema_json_in_xml_invalid_defaults_json_input
(
self
):
self
.
writeJsonSchema
(
valid_defaults
=
False
)
parameters
=
{
"number"
:
1
}
with
self
.
patchSlap
(
parameters
,
True
):
self
.
assertRaises
(
slapconfiguration
.
UserError
,
self
.
receiveParameters
,
)
def
test_jsonschema_shared_1_valid_defaults
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
shared
=
[{
"kind"
:
1
}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
valid
,
invalid
=
self
.
receiveSharedParameters
()
self
.
assertEqual
(
invalid
,
{})
self
.
assertEqual
(
list
(
valid
.
values
()),
[{
"kind"
:
1
,
"thing"
:
"hello"
}])
def
test_jsonschema_shared_2_valid_defaults
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
shared
=
[{
"kind"
:
2
}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
valid
,
invalid
=
self
.
receiveSharedParameters
()
self
.
assertEqual
(
invalid
,
{})
self
.
assertEqual
(
list
(
valid
.
values
()),
[{
"kind"
:
2
,
"thing"
:
42
}])
def
test_jsonschema_shared_1_invalid_defaults
(
self
):
self
.
writeJsonSchema
(
valid_defaults
=
False
)
parameters
=
{
"number"
:
1
,
"letter"
:
"a"
}
shared
=
[{
"kind"
:
1
}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
valid
,
invalid
=
self
.
receiveSharedParameters
()
self
.
assertEqual
(
valid
,
{})
self
.
assertEqual
(
list
(
invalid
.
values
()),
[{
"kind"
:
1
,
"thing"
:
1
}])
def
test_jsonschema_shared_2_invalid_defaults
(
self
):
self
.
writeJsonSchema
(
valid_defaults
=
False
)
parameters
=
{
"number"
:
1
,
"letter"
:
"a"
}
shared
=
[{
"kind"
:
2
}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
valid
,
invalid
=
self
.
receiveSharedParameters
()
self
.
assertEqual
(
valid
,
{})
invalid_values
=
list
(
invalid
.
values
())
self
.
assertEqual
(
invalid_values
,
[{
"kind"
:
2
,
"thing"
:
"forty-two"
}])
def
test_jsonschema_shared_2_valid_without_defaults
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
shared
=
[{
"kind"
:
2
}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
valid
,
_
=
self
.
receiveSharedParameters
(
options
=
())
self
.
assertEqual
(
list
(
valid
.
values
()),
shared
)
def
test_jsonschema_shared_2_valid_with_only_main_defaults
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
shared
=
[{
"kind"
:
2
}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
valid
,
_
=
self
.
receiveSharedParameters
({
'set-default'
:
'main'
})
self
.
assertEqual
(
list
(
valid
.
values
()),
shared
)
def
test_jsonschema_shared_2_valid_with_only_shared_defaults
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
shared
=
[{
"kind"
:
2
}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
valid
,
_
=
self
.
receiveSharedParameters
({
'set-default'
:
'shared'
})
self
.
assertEqual
(
list
(
valid
.
values
()),
[{
"kind"
:
2
,
"thing"
:
42
}])
def
test_jsonschema_shared_1_and_2_valid_defaults
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
shared
=
[{
"kind"
:
1
},
{
"kind"
:
2
}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
valid
,
invalid
=
self
.
receiveSharedParameters
()
self
.
assertEqual
(
invalid
,
{})
expected
=
[{
"kind"
:
1
,
"thing"
:
"hello"
},
{
"kind"
:
2
,
"thing"
:
42
}]
self
.
assertEqual
(
list
(
valid
.
values
()),
expected
)
def
test_jsonschema_shared_invalid_kind
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
shared
=
[{
"kind"
:
3
}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
valid
,
invalid
=
self
.
receiveSharedParameters
()
self
.
assertEqual
(
valid
,
{})
self
.
assertEqual
(
list
(
invalid
.
values
()),
[{
"kind"
:
3
}])
def
test_jsonschema_shared_1_invalid_thing
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
shared
=
[{
"kind"
:
1
,
"thing"
:
{}}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
valid
,
invalid
=
self
.
receiveSharedParameters
()
self
.
assertEqual
(
valid
,
{})
self
.
assertEqual
(
list
(
invalid
.
values
()),
[{
"kind"
:
1
,
"thing"
:
{}}])
def
test_jsonschema_shared_2_invalid_thing
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
shared
=
[{
"kind"
:
2
,
"thing"
:
{}}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
valid
,
invalid
=
self
.
receiveSharedParameters
()
self
.
assertEqual
(
valid
,
{})
self
.
assertEqual
(
list
(
invalid
.
values
()),
[{
"kind"
:
2
,
"thing"
:
{}}])
def
test_jsonschema_shared_valid_and_invalid
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
shared
=
[{
"kind"
:
1
},
{
"kind"
:
2
,
"thing"
:
"hello"
}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
valid
,
invalid
=
self
.
receiveSharedParameters
()
self
.
assertEqual
(
list
(
valid
.
values
()),
[{
"kind"
:
1
,
"thing"
:
"hello"
}])
self
.
assertEqual
(
list
(
invalid
.
values
()),
[{
"kind"
:
2
,
"thing"
:
"hello"
}])
def
test_jsonschema_shared_valid_and_invalid_skip_shared
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
shared
=
[{
"kind"
:
1
},
{
"kind"
:
2
,
"thing"
:
"hello"
}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
options
=
self
.
runJsonSchemaRecipe
({
'validate-parameters'
:
'main'
})
shared
=
options
[
'slave-instance-list'
]
self
.
assertEqual
(
shared
,
[
{
"slave_reference"
:
"SHARED0"
,
"kind"
:
1
},
{
"slave_reference"
:
"SHARED1"
,
"kind"
:
2
,
"thing"
:
"hello"
},
],
)
def
test_jsonschema_shared_valid_and_invalid_skip_main
(
self
):
self
.
writeJsonSchema
()
parameters
=
{
"number"
:
1
}
shared
=
[{
"kind"
:
1
},
{
"kind"
:
2
,
"thing"
:
"hello"
}]
with
self
.
patchSlap
(
parameters
,
True
,
shared
):
options
=
{
'validate-parameters'
:
'shared'
,
'set-default'
:
'all'
}
valid
,
invalid
=
self
.
receiveSharedParameters
(
options
)
self
.
assertEqual
(
list
(
valid
.
values
()),
[{
"kind"
:
1
,
"thing"
:
"hello"
}])
self
.
assertEqual
(
list
(
invalid
.
values
()),
[{
"kind"
:
2
,
"thing"
:
"hello"
}])
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment