Skip to content

Commit

Permalink
Support for Property Definitions (#308)
Browse files Browse the repository at this point in the history
support for property definitions

---

Co-authored-by: Rocktavious <[email protected]>
Co-authored-by: Kyle <[email protected]>
Co-authored-by: David Bloss <[email protected]>
  • Loading branch information
4 people committed Dec 14, 2023
1 parent aaf9641 commit 26b6ad8
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changes/unreleased/Feature-20231115-143536.yaml
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
89 changes: 89 additions & 0 deletions property.go
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)
}
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)
}
135 changes: 135 additions & 0 deletions property_test.go
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
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)
}

0 comments on commit 26b6ad8

Please sign in to comment.