Skip to content
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: 6 additions & 0 deletions .changes/unreleased/Feature-20260717-100000.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Feature
body: Add CreateIntegrationKubernetes and UpdateIntegrationKubernetes client methods
along with KubernetesIntegrationInput and a KubernetesIntegration fragment exposing
ExtractDefinition and TransformDefinition, so a Kubernetes integration's ETL config
can be managed via the API.
time: 2026-07-17T10:00:00.000000Z
38 changes: 38 additions & 0 deletions integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ type GoogleCloudIntegrationFragment struct {
TagsOverrideOwnership bool `graphql:"tagsOverrideOwnership"`
}

type KubernetesIntegrationFragment struct {
ExtractDefinition string `graphql:"extractDefinition"`
TransformDefinition string `graphql:"transformDefinition"`
}

type NewRelicIntegrationFragment struct {
BaseUrl string `graphql:"baseUrl"`
AccountKey string `graphql:"accountKey"`
Expand All @@ -51,7 +56,17 @@ type AWSIntegrationInput struct {
RegionOverride *[]string `json:"regionOverride,omitempty"`
}

type KubernetesIntegrationInput struct {
ExtractDefinition *YAML `json:"extractDefinition,omitempty"`
Name *Nullable[string] `json:"name,omitempty"`
TransformDefinition *YAML `json:"transformDefinition,omitempty"`
}

func (awsIntegrationInput AWSIntegrationInput) GetGraphQLType() string { return "AwsIntegrationInput" }
func (kubernetesIntegrationInput KubernetesIntegrationInput) GetGraphQLType() string {
return "KubernetesIntegrationInput"
}

func (newRelicIntegrationInput NewRelicIntegrationInput) GetGraphQLType() string {
return "NewRelicIntegrationInput"
}
Expand Down Expand Up @@ -234,6 +249,29 @@ func (client *Client) UpdateIntegrationGCP(identifier string, input GoogleCloudI
return &m.Payload.Integration, HandleErrors(err, m.Payload.Errors)
}

func (client *Client) CreateIntegrationKubernetes(input KubernetesIntegrationInput) (*Integration, error) {
var m struct {
Payload IntegrationCreatePayload `graphql:"kubernetesIntegrationCreate(input: $input)"`
}
v := PayloadVariables{
"input": input,
}
err := client.Mutate(&m, v, WithName("KubernetesIntegrationCreate"))
return &m.Payload.Integration, HandleErrors(err, m.Payload.Errors)
}

func (client *Client) UpdateIntegrationKubernetes(identifier string, input KubernetesIntegrationInput) (*Integration, error) {
var m struct {
Payload IntegrationUpdatePayload `graphql:"kubernetesIntegrationUpdate(integration: $integration input: $input)"`
}
v := PayloadVariables{
"integration": *NewIdentifier(identifier),
"input": input,
}
err := client.Mutate(&m, v, WithName("KubernetesIntegrationUpdate"))
return &m.Payload.Integration, HandleErrors(err, m.Payload.Errors)
}

func (client *Client) IntegrationReactivate(identifier string) (*Integration, error) {
var m struct {
Payload IntegrationReactivatePayload `graphql:"integrationReactivate(integration: $integration)"`
Expand Down
72 changes: 72 additions & 0 deletions integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,42 @@ func TestCreateGoogleCloudIntegration(t *testing.T) {
}, result.Projects)
}

func TestCreateKubernetesIntegration(t *testing.T) {
// Arrange
testRequest := autopilot.NewTestRequest(
`mutation KubernetesIntegrationCreate($input:KubernetesIntegrationInput!){kubernetesIntegrationCreate(input: $input){integration{{ template "integration_request" }},errors{message,path}}}`,
`{"input": { "name": "Kubernetes", "extractDefinition": "extractors:\n- external_kind: Deployment\n", "transformDefinition": "transforms:\n- infrastructure_resource: Deployment\n" }}`,
`{"data": {
"kubernetesIntegrationCreate": {
"integration": {
{{ template "id1" }},
"name": "Kubernetes",
"type": "kubernetes",
"createdAt": "2026-07-17T16:25:29.574450Z",
"installedAt": "2026-07-17T16:25:28.541124Z",
"extractDefinition": "extractors:\n- external_kind: Deployment\n",
"transformDefinition": "transforms:\n- infrastructure_resource: Deployment\n"
},
"errors": []
}}}`,
)
client := BestTestClient(t, "integration/create_kubernetes", testRequest)
extractDefinition := opslevel.YAML("extractors:\n- external_kind: Deployment\n")
transformDefinition := opslevel.YAML("transforms:\n- infrastructure_resource: Deployment\n")
// Act
result, err := client.CreateIntegrationKubernetes(opslevel.KubernetesIntegrationInput{
Name: opslevel.RefOf("Kubernetes"),
ExtractDefinition: &extractDefinition,
TransformDefinition: &transformDefinition,
})
// Assert
autopilot.Equals(t, nil, err)
autopilot.Equals(t, id1, result.Id)
autopilot.Equals(t, "Kubernetes", result.Name)
autopilot.Equals(t, "extractors:\n- external_kind: Deployment\n", result.ExtractDefinition)
autopilot.Equals(t, "transforms:\n- infrastructure_resource: Deployment\n", result.TransformDefinition)
}

func TestCreateNewRelicIntegration(t *testing.T) {
// Arrange
testRequest := autopilot.NewTestRequest(
Expand Down Expand Up @@ -368,6 +404,42 @@ func TestUpdateGoogleCloudIntegration(t *testing.T) {
}, result.Projects)
}

func TestUpdateKubernetesIntegration(t *testing.T) {
// Arrange
testRequest := autopilot.NewTestRequest(
`mutation KubernetesIntegrationUpdate($input:KubernetesIntegrationInput!$integration:IdentifierInput!){kubernetesIntegrationUpdate(integration: $integration input: $input){integration{{ template "integration_request" }},errors{message,path}}}`,
`{"integration": { {{ template "id1" }} }, "input": { "name": "Kubernetes Updated", "extractDefinition": "extractors:\n- external_kind: StatefulSet\n", "transformDefinition": "transforms:\n- infrastructure_resource: StatefulSet\n" }}`,
`{"data": {
"kubernetesIntegrationUpdate": {
"integration": {
{{ template "id1" }},
"name": "Kubernetes Updated",
"type": "kubernetes",
"createdAt": "2026-07-17T16:25:29.574450Z",
"installedAt": "2026-07-17T16:25:28.541124Z",
"extractDefinition": "extractors:\n- external_kind: StatefulSet\n",
"transformDefinition": "transforms:\n- infrastructure_resource: StatefulSet\n"
},
"errors": []
}}}`,
)
client := BestTestClient(t, "integration/update_kubernetes", testRequest)
extractDefinition := opslevel.YAML("extractors:\n- external_kind: StatefulSet\n")
transformDefinition := opslevel.YAML("transforms:\n- infrastructure_resource: StatefulSet\n")
// Act
result, err := client.UpdateIntegrationKubernetes(string(id1), opslevel.KubernetesIntegrationInput{
Name: opslevel.RefOf("Kubernetes Updated"),
ExtractDefinition: &extractDefinition,
TransformDefinition: &transformDefinition,
})
// Assert
autopilot.Equals(t, nil, err)
autopilot.Equals(t, id1, result.Id)
autopilot.Equals(t, "Kubernetes Updated", result.Name)
autopilot.Equals(t, "extractors:\n- external_kind: StatefulSet\n", result.ExtractDefinition)
autopilot.Equals(t, "transforms:\n- infrastructure_resource: StatefulSet\n", result.TransformDefinition)
}

func TestUpdateNewRelicIntegration(t *testing.T) {
// Arrange
testRequest := autopilot.NewTestRequest(
Expand Down
1 change: 1 addition & 0 deletions interfaces.go

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

2 changes: 1 addition & 1 deletion testdata/templates/integrations.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@
{{ end }}

{{- define "integration_request" -}}
{id,name,type,displayName,webhookUrl,createdAt,installedAt,... on AwsIntegration{iamRole,externalId,awsTagsOverrideOwnership,ownershipTagKeys,regionOverride},... on AzureResourcesIntegration{aliases,ownershipTagKeys,subscriptionId,tagsOverrideOwnership,tenantId},... on GoogleCloudIntegration{aliases,clientEmail,ownershipTagKeys,projects{id,name,url},tagsOverrideOwnership},... on NewRelicIntegration{baseUrl,accountKey}}
{id,name,type,displayName,webhookUrl,createdAt,installedAt,... on AwsIntegration{iamRole,externalId,awsTagsOverrideOwnership,ownershipTagKeys,regionOverride},... on AzureResourcesIntegration{aliases,ownershipTagKeys,subscriptionId,tagsOverrideOwnership,tenantId},... on GoogleCloudIntegration{aliases,clientEmail,ownershipTagKeys,projects{id,name,url},tagsOverrideOwnership},... on KubernetesIntegration{extractDefinition,transformDefinition},... on NewRelicIntegration{baseUrl,accountKey}}
{{- end }}
6 changes: 6 additions & 0 deletions yaml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package opslevel

// YAML represents a YAML document serialized as a string for use with the OpsLevel API.
type YAML string

func (y YAML) GetGraphQLType() string { return "YAML" }
Loading