Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Repeated parameters #679

Merged
merged 10 commits into from
Jan 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions docs/guide/service/emit-an-event.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ To create an event, the first step is to update the Service's [`mesg.yml`](servi
| **description** | `""` | `String` | Description of the data |
| **type** | `String` | [`Type`](emit-an-event.md#type-of-your-data) | Type of data |
| **optional** | `false` | `boolean` | Mark the data as optional |
| **repeated** | `false` | `boolean` | Define this data as an array of the type selected |

### Data's type

Expand All @@ -52,14 +53,15 @@ events:
data:
foo:
name: "Foo"
description: "Foo is the first data"
description: "Foo is a string"
type: String
optional: false
bar:
name: "Bar"
description: "Bar is the second data"
description: "Bar is an optional array of boolean"
type: Boolean
optional: true
repeated: true
...
```

Expand Down
6 changes: 4 additions & 2 deletions docs/guide/service/listen-for-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ The first step is to declare the tasks that the service will be able to execute
| **description** | `""` | `String` | Description of the parameter. |
| **type** | `String` | [`Type`](listen-for-tasks.md#type-of-your-data) | Type of the parameter. |
| **optional** | `false` | `Boolean` | If true, this parameter is considered as optional and might remain empty. |
| **repeated** | `false` | `Boolean` | Define this parameter as an array of the type selected |

### Type of parameter

Expand All @@ -62,14 +63,15 @@ tasks:
inputs:
inputX:
name: "Input x"
description: "Foo is the first data"
description: "Foo is a string"
type: String
optional: false
inputY:
name: "Input y"
description: "Bar is the second data"
description: "Bar is an optional array of boolean"
type: Boolean
optional: true
repeated: true
outputs:
outputX:
name: "OutputX"
Expand Down
1 change: 1 addition & 0 deletions interface/grpc/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ func toProtoParameters(params []*service.Parameter) []*coreapi.Parameter {
Name: param.Name,
Description: param.Description,
Type: param.Type,
Repeated: param.Repeated,
Optional: param.Optional,
}
}
Expand Down
245 changes: 127 additions & 118 deletions protobuf/coreapi/api.pb.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions protobuf/coreapi/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ message Parameter {
string description = 2; // Parameter's description.
string type = 3; // Parameter's type: `String`, `Number`, `Boolean` or `Object`.
bool optional = 4; // Set the parameter as optional.
bool repeated = 9; // Mark a parameter as an array of the defined type
}

// A dependency is a configuration of an other Docker container that runs separately from the service.
Expand Down
4 changes: 2 additions & 2 deletions service/importer/assets/schema.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions service/importer/assets/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@
"optional": {
"type": "boolean"
},
"repeated": {
"type": "boolean"
},
"type": {
"type": "string",
"enum": [
Expand Down
3 changes: 3 additions & 0 deletions service/importer/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,7 @@ type Parameter struct {

// Optional indicates if parameter is optional.
Optional bool `yaml:"optional"`

// Repeated is to have an array of this parameter
Repeated bool `yaml:"repeated"`
}
1 change: 1 addition & 0 deletions service/inject_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ func (s *Service) defParametersToService(params map[string]*importer.Parameter)
Description: param.Description,
Type: param.Type,
Optional: param.Optional,
Repeated: param.Repeated,
}
}
return ps
Expand Down
3 changes: 3 additions & 0 deletions service/parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ type Parameter struct {

// Optional indicates if parameter is optional.
Optional bool `hash:"name:5"`

// Repeated is to have an array of this parameter
Repeated bool `hash:"name:6"`
}
14 changes: 13 additions & 1 deletion service/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,19 @@ func (v *parameterValidator) Validate(value interface{}) *ParameterWarning {
}
return v.newParameterWarning("required")
}

if v.parameter.Repeated {
// Check if the value is a slice
array, ok := value.([]interface{})
if !ok {
return v.newParameterWarning("not an array")
}
for _, x := range array {
if warning := v.validateType(x); warning != nil {
return warning
}
}
return nil
}
return v.validateType(value)
}

Expand Down
87 changes: 62 additions & 25 deletions service/validation_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package service

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -28,6 +29,11 @@ var eventDataSchema = []*Parameter{
Key: "object",
Type: "Object",
},
{
Key: "array",
Type: "String",
Repeated: true,
},
}

func validateParameterData(paramKey string, data interface{}) bool {
Expand Down Expand Up @@ -74,32 +80,63 @@ func TestObject(t *testing.T) {
require.False(t, validateParameterData("object", 42))
}

func TestArray(t *testing.T) {
require.True(t, validateParameterData("array", []interface{}{"foo", "bar"}))
require.True(t, validateParameterData("array", []interface{}{}))
require.False(t, validateParameterData("array", []interface{}{10}))
require.False(t, validateParameterData("array", 42))
}

func TestValidateParameters(t *testing.T) {
require.Len(t, validateParametersSchema(eventDataSchema, map[string]interface{}{
"string": "hello",
"number": 10,
"boolean": true,
"object": map[string]interface{}{
"foo": "bar",
tests := []struct {
data string
errors int
}{
{
data: `{
"string": "hello",
"number": 10,
"boolean": true,
"object": {
"foo": "bar"
},
"array": ["foo", "bar"]
}`,
errors: 0,
},
}), 0)
require.Len(t, validateParametersSchema(eventDataSchema, map[string]interface{}{
"optional": "yeah",
"string": "hello",
"number": 10,
"boolean": true,
"object": map[string]interface{}{
"foo": "bar",
{
data: `{
"optional": "yeah",
"string": "hello",
"number": 10,
"boolean": true,
"object": {
"foo": "bar"
},
"array": ["foo", "bar"]
}`,
errors: 0,
},
}), 0)
// 4 errors
// - not required string
// - invalid number
// - invalid boolean
// - invalid object
require.Len(t, validateParametersSchema(eventDataSchema, map[string]interface{}{
"number": "string",
"boolean": 42,
"object": false,
}), 4)
{
// 5 errors
// - not required string
// - invalid number
// - invalid boolean
// - invalid object
// - invalid array
data: `{
"number": "string",
"boolean": 42,
"object": false,
"array": 42
}`,
errors: 5,
},
}

for _, test := range tests {
var data map[string]interface{}
require.NoError(t, json.Unmarshal([]byte(test.data), &data))
require.Len(t, validateParametersSchema(eventDataSchema, data), test.errors)
}
}