-
Notifications
You must be signed in to change notification settings - Fork 13
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
Support for Property Definitions #308
Merged
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
28f4c7d
add type methods for better interface
rocktavious 3ce7540
fix linting
rocktavious 417c7cc
initial property code
6cd046e
test for create propdef
f437be2
get delete tests
1629bfe
list test
06dfafa
property defs
1f5dfd7
todoz
591d32f
pass tests
0b47368
Apply suggestions from code review
efce4eb
more changes
b8451e7
nested ol.JSON has too many escape chars
1c44438
temp work - trying to use templating
af9a7ea
quoting issue
7279108
fixup delete test
25c75e3
fix list request by changing read type from JSON to string
0e09ce2
fixup get test
d85a5bd
pear programming
94b9a6b
create test
5bd961f
list test passing
a44649e
identifier pointer
15ad1ed
Apply suggestions from code review
938dcb4
fix property definition create test after adapting for JSONString
694a9f3
update changie timestamp
41b576c
remove deletedId, deletedAlias
ad9be49
make PropertyDefinition.Schema field a JSONString type, update tests
davidbloss 0d17fee
fixed types and tests
davidbloss 88a0df4
Merge pull request #325 from OpsLevel/db/set-PropertyDefinition-schem…
davidbloss File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
kind: Feature | ||
body: Add support for Property Definitions | ||
time: 2023-12-07T15:22:26.29648-05:00 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package opslevel | ||
|
||
import "fmt" | ||
|
||
type PropertyDefinitionInput struct { | ||
Name string `json:"name"` | ||
Schema JSONString `json:"schema"` | ||
} | ||
|
||
type PropertyDefinition struct { | ||
Aliases []string `graphql:"aliases" json:"aliases"` | ||
Id ID `graphql:"id" json:"id"` | ||
Name string `graphql:"name" json:"name"` | ||
Schema JSON `json:"schema" scalar:"true"` // Do not add graphql struct tag here | ||
} | ||
|
||
type PropertyDefinitionConnection struct { | ||
Nodes []PropertyDefinition | ||
PageInfo PageInfo | ||
TotalCount int `graphql:"-"` | ||
} | ||
|
||
func (client *Client) CreatePropertyDefinition(input PropertyDefinitionInput) (*PropertyDefinition, error) { | ||
var m struct { | ||
Payload struct { | ||
Definition PropertyDefinition `graphql:"definition"` | ||
Errors []OpsLevelErrors `graphql:"errors"` | ||
} `graphql:"propertyDefinitionCreate(input: $input)"` | ||
} | ||
v := PayloadVariables{ | ||
"input": input, | ||
} | ||
err := client.Mutate(&m, v, WithName("PropertyDefinitionCreate")) | ||
return &m.Payload.Definition, HandleErrors(err, m.Payload.Errors) | ||
} | ||
|
||
func (client *Client) GetPropertyDefinition(input string) (*PropertyDefinition, error) { | ||
var q struct { | ||
Account struct { | ||
Definition PropertyDefinition `graphql:"propertyDefinition(input: $input)"` | ||
} | ||
} | ||
v := PayloadVariables{ | ||
"input": *NewIdentifier(input), | ||
} | ||
err := client.Query(&q, v, WithName("PropertyDefinitionGet")) | ||
if q.Account.Definition.Id == "" { | ||
err = fmt.Errorf("PropertyDefinition with ID or Alias matching '%s' not found", input) | ||
This conversation was marked as resolved.
Show resolved
Hide resolved
|
||
} | ||
return &q.Account.Definition, HandleErrors(err, nil) | ||
} | ||
|
||
func (client *Client) ListPropertyDefinitions(variables *PayloadVariables) (PropertyDefinitionConnection, error) { | ||
var q struct { | ||
Account struct { | ||
Definitions PropertyDefinitionConnection `graphql:"propertyDefinitions(after: $after, first: $first)"` | ||
} | ||
} | ||
if variables == nil { | ||
variables = client.InitialPageVariablesPointer() | ||
} | ||
if err := client.Query(&q, *variables, WithName("PropertyDefinitionList")); err != nil { | ||
return PropertyDefinitionConnection{}, err | ||
} | ||
for q.Account.Definitions.PageInfo.HasNextPage { | ||
(*variables)["after"] = q.Account.Definitions.PageInfo.End | ||
resp, err := client.ListPropertyDefinitions(variables) | ||
if err != nil { | ||
return PropertyDefinitionConnection{}, err | ||
} | ||
q.Account.Definitions.Nodes = append(q.Account.Definitions.Nodes, resp.Nodes...) | ||
q.Account.Definitions.PageInfo = resp.PageInfo | ||
q.Account.Definitions.TotalCount += len(q.Account.Definitions.Nodes) | ||
} | ||
return q.Account.Definitions, nil | ||
} | ||
|
||
func (client *Client) DeletePropertyDefinition(input string) error { | ||
var m struct { | ||
Payload struct { | ||
Errors []OpsLevelErrors `graphql:"errors"` | ||
} `graphql:"propertyDefinitionDelete(resource: $input)"` | ||
} | ||
v := PayloadVariables{ | ||
"input": *NewIdentifier(input), | ||
} | ||
err := client.Mutate(&m, v, WithName("PropertyDefinitionDelete")) | ||
return HandleErrors(err, m.Payload.Errors) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
package opslevel_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
ol "github.com/opslevel/opslevel-go/v2023" | ||
"github.com/rocktavious/autopilot/v2023" | ||
) | ||
|
||
const schemaString = `{"$ref":"#/$defs/MyProp","$defs":{"MyProp":{"properties":{"name":{"type":"string","title":"the name","description":"The name of a friend","default":"alex","examples":["joe","lucy"]}},"additionalProperties":false,"type":"object","required":["name"]}}}` | ||
|
||
func TestCreatePropertyDefinition(t *testing.T) { | ||
// Arrange | ||
This conversation was marked as resolved.
Show resolved
Hide resolved
|
||
schema := ol.NewJSON(schemaString) | ||
expectedPropertyDefinition := autopilot.Register[ol.PropertyDefinition]("expected_property_definition", ol.PropertyDefinition{ | ||
Aliases: []string{"my_prop"}, | ||
Id: "XXX", | ||
Name: "my-prop", | ||
Schema: schema, | ||
}) | ||
propertyDefinitionInput := autopilot.Register[ol.PropertyDefinitionInput]("property_definition_input", ol.PropertyDefinitionInput{ | ||
Name: "my-prop", | ||
Schema: ol.JSONString(schemaString), | ||
}) | ||
testRequest := NewTestRequest( | ||
`"mutation PropertyDefinitionCreate($input:PropertyDefinitionInput!){propertyDefinitionCreate(input: $input){definition{aliases,id,name,schema},errors{message,path}}}"`, | ||
`{"input": {{ template "property_definition_input" }} }`, | ||
fmt.Sprintf(`{"data":{"propertyDefinitionCreate":{"definition": {"aliases":["my_prop"],"id":"XXX","name":"my-prop","schema": %s}, "errors":[] }}}`, schema.ToJSON()), | ||
) | ||
client := BestTestClient(t, "properties/definition_create", testRequest) | ||
|
||
// Act | ||
actualPropertyDefinition, err := client.CreatePropertyDefinition(propertyDefinitionInput) | ||
|
||
// Assert | ||
autopilot.Ok(t, err) | ||
autopilot.Equals(t, expectedPropertyDefinition, *actualPropertyDefinition) | ||
autopilot.Equals(t, ol.JSON(propertyDefinitionInput.Schema.Map()), actualPropertyDefinition.Schema) | ||
} | ||
|
||
func TestDeletePropertyDefinition(t *testing.T) { | ||
// Arrange | ||
testRequest := NewTestRequest( | ||
`"mutation PropertyDefinitionDelete($input:IdentifierInput!){propertyDefinitionDelete(resource: $input){errors{message,path}}}"`, | ||
`{"input":{"alias":"my_prop"}}`, | ||
`{"data":{"propertyDefinitionDelete":{"errors":[]}}}`, | ||
) | ||
client := BestTestClient(t, "properties/definition_delete", testRequest) | ||
|
||
// Act | ||
err := client.DeletePropertyDefinition("my_prop") | ||
|
||
// Assert | ||
autopilot.Ok(t, err) | ||
} | ||
|
||
func TestGetPropertyDefinition(t *testing.T) { | ||
// Arrange | ||
schema := ol.NewJSON(schemaString) | ||
expectedPropertyDefinition := autopilot.Register[ol.PropertyDefinition]("expected_property_definition", | ||
ol.PropertyDefinition{ | ||
Aliases: []string{"my_prop"}, | ||
Id: "XXX", | ||
Name: "my-prop", | ||
Schema: schema, | ||
}) | ||
testRequest := NewTestRequest( | ||
`"query PropertyDefinitionGet($input:IdentifierInput!){account{propertyDefinition(input: $input){aliases,id,name,schema}}}"`, | ||
`{"input":{"alias":"my_prop"}}`, | ||
fmt.Sprintf(`{"data":{"account":{"propertyDefinition": {"aliases":["my_prop"],"id":"XXX","name":"my-prop","schema": %s }}}}`, schema.ToJSON()), | ||
) | ||
client := BestTestClient(t, "properties/definition_get", testRequest) | ||
|
||
// Act | ||
property, err := client.GetPropertyDefinition("my_prop") | ||
|
||
// Assert | ||
autopilot.Ok(t, err) | ||
autopilot.Equals(t, "XXX", string(property.Id)) | ||
autopilot.Equals(t, expectedPropertyDefinition, *property) | ||
autopilot.Equals(t, "my-prop", property.Name) | ||
autopilot.Equals(t, schema, property.Schema) | ||
} | ||
|
||
func TestListPropertyDefinitions(t *testing.T) { | ||
// Arrange | ||
schema := ol.NewJSON(schemaString) | ||
expectedPropDefsPageOne := autopilot.Register[[]ol.PropertyDefinition]("property_definitions", []ol.PropertyDefinition{ | ||
{ | ||
Aliases: []string{"prop1"}, | ||
Id: "XXX", | ||
Name: "prop1", | ||
Schema: ol.NewJSON(schemaString), | ||
}, | ||
{ | ||
Aliases: []string{"prop2"}, | ||
Id: "XXX", | ||
Name: "prop2", | ||
Schema: ol.NewJSON(schemaString), | ||
}, | ||
}) | ||
expectedPropDefPageTwo := autopilot.Register[ol.PropertyDefinition]("property_definition_3", ol.PropertyDefinition{ | ||
Aliases: []string{"prop3"}, | ||
Id: "XXX", | ||
Name: "prop3", | ||
Schema: ol.NewJSON(schemaString), | ||
}) | ||
testRequestOne := NewTestRequest( | ||
`"query PropertyDefinitionList($after:String!$first:Int!){account{propertyDefinitions(after: $after, first: $first){nodes{aliases,id,name,schema},{{ template "pagination_request" }}}}}"`, | ||
`{{ template "pagination_initial_query_variables" }}`, | ||
fmt.Sprintf(`{"data":{"account":{"propertyDefinitions":{"nodes":[{"aliases":["prop1"],"id":"XXX","name":"prop1","schema": %s},{"aliases":["prop2"],"id":"XXX","name":"prop2","schema": %s}],{{ template "pagination_initial_pageInfo_response" }}}}}}`, schema.ToJSON(), schema.ToJSON()), | ||
) | ||
testRequestTwo := NewTestRequest( | ||
`"query PropertyDefinitionList($after:String!$first:Int!){account{propertyDefinitions(after: $after, first: $first){nodes{aliases,id,name,schema},{{ template "pagination_request" }}}}}"`, | ||
`{{ template "pagination_second_query_variables" }}`, | ||
fmt.Sprintf(`{"data":{"account":{"propertyDefinitions":{"nodes":[{"aliases":["prop3"],"id":"XXX","name":"prop3","schema": %s}],{{ template "pagination_second_pageInfo_response" }}}}}}`, schema.ToJSON()), | ||
) | ||
requests := []TestRequest{testRequestOne, testRequestTwo} | ||
client := BestTestClient(t, "properties/definition_list", requests...) | ||
|
||
// Act | ||
properties, err := client.ListPropertyDefinitions(nil) | ||
result := properties.Nodes | ||
|
||
// Assert | ||
autopilot.Ok(t, err) | ||
autopilot.Equals(t, 3, len(result)) | ||
autopilot.Equals(t, expectedPropDefsPageOne[0], result[0]) | ||
autopilot.Equals(t, expectedPropDefsPageOne[1], result[1]) | ||
autopilot.Equals(t, expectedPropDefPageTwo, result[2]) | ||
autopilot.Equals(t, expectedPropDefsPageOne[0].Schema, result[0].Schema) | ||
autopilot.Equals(t, expectedPropDefsPageOne[1].Schema, result[1].Schema) | ||
autopilot.Equals(t, expectedPropDefPageTwo.Schema, result[2].Schema) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well you can add
graphql
struct tags if you neeed - you actually just needscalar:"true"
becauseJSON
is a custom scalar type we wrote.