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

[datadog_service_definition_yaml] Support service definition schema v2.2 #2126

Merged
merged 8 commits into from
Oct 10, 2023
55 changes: 53 additions & 2 deletions datadog/resource_datadog_service_definition_yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"sort"
"strconv"
"strings"

"github.com/terraform-providers/terraform-provider-datadog/datadog/internal/utils"
Expand Down Expand Up @@ -247,10 +248,60 @@ func isValidServiceDefinition(i interface{}, k string) (warnings []string, error
return warnings, errors
}

type semVersion struct {
major int
minor int
patch int
}

func parseSemVersion(version string) (semVersion, error) {
if !strings.HasPrefix(version, "v") {
return semVersion{}, fmt.Errorf("missing prefix v: %s", version)
}

version = version[1:]
parts := strings.Split(version, ".")

// Initialize the default values
var sVersion semVersion

// Parse major version
major, err := strconv.Atoi(parts[0])
if err != nil {
return semVersion{}, fmt.Errorf("error parsing major version: %v", err)
}
sVersion.major = major

// If minor version is provided
if len(parts) > 1 {
minor, err := strconv.Atoi(parts[1])
if err != nil {
return semVersion{}, fmt.Errorf("error parsing minor version: %v", err)
}
sVersion.minor = minor
}

// If patch version is provided
if len(parts) > 2 {
patch, err := strconv.Atoi(parts[2])
if err != nil {
return semVersion{}, fmt.Errorf("error parsing patch version: %v", err)
}
sVersion.patch = patch
}

return sVersion, nil
}

func isValidDatadogServiceDefinition(attrMap map[string]interface{}, k string) (warnings []string, errors []error) {
if schemaVersion, ok := attrMap["schema-version"].(string); ok {
if schemaVersion != "v2" && schemaVersion != "v2.1" {
errors = append(errors, fmt.Errorf("schema-version must be >= v2, but %s is used", schemaVersion))
version, err := parseSemVersion(schemaVersion)
if err != nil {
errors = append(errors, fmt.Errorf("schema-version is invalid: %s", schemaVersion))
} else {
if version.major < 2 {
errors = append(errors, fmt.Errorf("schema-version must be >= v2, but %s is used", schemaVersion))
}
}
} else {
errors = append(errors, fmt.Errorf("schema-version is missing: %q", k))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2023-10-06T15:07:19.795264-04:00
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
version: 1
interactions:
- request:
body: "schema-version: v2.2\ndd-service: tf-testaccdatadogservicedefinition_basicv2_2-local-1696619239\ncontacts:\n - contact: [email protected]\n name: Team Email\n type: email\nextensions:\n myorgextension: extensionvalue\nintegrations:\n opsgenie:\n region: US\n service-url: https://my-org.opsgenie.com/service/123e4567-e89b-12d3-a456-426614174000\n pagerduty:\n service-url: https://my-org.pagerduty.com/service-directory/PMyService\nlinks:\n - name: Architecture\n type: doc\n provider: Gigoogle drivetHub\n url: https://my-runbook\n - name: Runbook\n type: runbook\n url: https://my-runbook\n - name: Source Code\n type: repo\n provider: GitHub\n url: https://github.com/DataDog/schema\ntags:\n - my:tag\n - service:tag\nteam: my-team \nlanguages:\n - go\n - python\nservice-type: web\n"
form: {}
headers:
Content-Type:
- application/json
url: https://api.datadoghq.com/api/v2/services/definitions
method: POST
response:
body: |
{"data":[{"type":"service-definition","attributes":{"meta":{"last-modified-time":"2023-10-06T19:07:21.086499009Z","github-html-url":"","ingestion-source":"api","origin":"dd_terraform","origin-detail":"","warnings":[],"ingested-schema-version":"v2.2"},"schema":{"schema-version":"v2.2","dd-service":"tf-testaccdatadogservicedefinition_basicv2_2-local-1696619239","team":"my-team","contacts":[{"name":"Team Email","type":"email","contact":"[email protected]"}],"links":[{"name":"Architecture","type":"doc","provider":"Gigoogle drivetHub","url":"https://my-runbook"},{"name":"Runbook","type":"runbook","url":"https://my-runbook"},{"name":"Source Code","type":"repo","provider":"GitHub","url":"https://github.com/DataDog/schema"}],"tags":["my:tag","service:tag"],"integrations":{"pagerduty":{"service-url":"https://my-org.pagerduty.com/service-directory/PMyService"},"opsgenie":{"service-url":"https://my-org.opsgenie.com/service/123e4567-e89b-12d3-a456-426614174000","region":"US"}},"extensions":{"myorgextension":"extensionvalue"},"service-type":"web","languages":["go","python"]}}}]}
headers:
Content-Type:
- application/json
status: 200 OK
code: 200
duration: ""
- request:
body: ""
form: {}
headers:
Content-Type:
- application/json
url: https://api.datadoghq.com/api/v2/services/definitions/tf-testaccdatadogservicedefinition_basicv2_2-local-1696619239
method: GET
response:
body: |
{"errors":["Not Found"],"error_details":[{}]}
headers:
Content-Type:
- application/json
status: 404 Not Found
code: 404
duration: ""
- request:
body: ""
form: {}
headers:
Content-Type:
- application/json
url: https://api.datadoghq.com/api/v2/services/definitions/tf-testaccdatadogservicedefinition_basicv2_2-local-1696619239
method: GET
response:
body: |
{"data":{"type":"service-definition","id":"39c14f488ab7a1f6b54c0641478beb77","attributes":{"meta":{"last-modified-time":"2023-10-06T19:07:21Z","github-html-url":"","ingestion-source":"api","origin":"dd_terraform","origin-detail":"","warnings":[],"ingested-schema-version":"v2.2"},"schema":{"schema-version":"v2.2","dd-service":"tf-testaccdatadogservicedefinition_basicv2_2-local-1696619239","team":"my-team","contacts":[{"name":"Team Email","type":"email","contact":"[email protected]"}],"links":[{"name":"Architecture","type":"doc","provider":"Gigoogle drivetHub","url":"https://my-runbook"},{"name":"Runbook","type":"runbook","url":"https://my-runbook"},{"name":"Source Code","type":"repo","provider":"GitHub","url":"https://github.com/DataDog/schema"}],"tags":["my:tag","service:tag"],"integrations":{"pagerduty":{"service-url":"https://my-org.pagerduty.com/service-directory/PMyService"},"opsgenie":{"service-url":"https://my-org.opsgenie.com/service/123e4567-e89b-12d3-a456-426614174000","region":"US"}},"extensions":{"myorgextension":"extensionvalue"},"service-type":"web","languages":["go","python"]}}}}
headers:
Content-Type:
- application/json
status: 200 OK
code: 200
duration: ""
- request:
body: ""
form: {}
headers:
Content-Type:
- application/json
url: https://api.datadoghq.com/api/v2/services/definitions/tf-testaccdatadogservicedefinition_basicv2_2-local-1696619239
method: GET
response:
body: |
{"data":{"type":"service-definition","id":"39c14f488ab7a1f6b54c0641478beb77","attributes":{"meta":{"last-modified-time":"2023-10-06T19:07:21Z","github-html-url":"","ingestion-source":"api","origin":"dd_terraform","origin-detail":"","warnings":[],"ingested-schema-version":"v2.2"},"schema":{"schema-version":"v2.2","dd-service":"tf-testaccdatadogservicedefinition_basicv2_2-local-1696619239","team":"my-team","contacts":[{"name":"Team Email","type":"email","contact":"[email protected]"}],"links":[{"name":"Architecture","type":"doc","provider":"Gigoogle drivetHub","url":"https://my-runbook"},{"name":"Runbook","type":"runbook","url":"https://my-runbook"},{"name":"Source Code","type":"repo","provider":"GitHub","url":"https://github.com/DataDog/schema"}],"tags":["my:tag","service:tag"],"integrations":{"pagerduty":{"service-url":"https://my-org.pagerduty.com/service-directory/PMyService"},"opsgenie":{"service-url":"https://my-org.opsgenie.com/service/123e4567-e89b-12d3-a456-426614174000","region":"US"}},"extensions":{"myorgextension":"extensionvalue"},"service-type":"web","languages":["go","python"]}}}}
headers:
Content-Type:
- application/json
status: 200 OK
code: 200
duration: ""
- request:
body: ""
form: {}
headers:
Content-Type:
- application/json
url: https://api.datadoghq.com/api/v2/services/definitions/tf-testaccdatadogservicedefinition_basicv2_2-local-1696619239
method: DELETE
response:
body: ""
headers:
Content-Type:
- text/html; charset=utf-8
status: 204 No Content
code: 204
duration: ""
- request:
body: ""
form: {}
headers:
Content-Type:
- application/json
url: https://api.datadoghq.com/api/v2/services/definitions/tf-testaccdatadogservicedefinition_basicv2_2-local-1696619239
method: GET
response:
body: |
{"data":{"type":"service-definition","id":"39c14f488ab7a1f6b54c0641478beb77","attributes":{"meta":{"last-modified-time":"2023-10-06T19:07:21Z","github-html-url":"","ingestion-source":"api","origin":"dd_terraform","origin-detail":"","warnings":[],"ingested-schema-version":"v2.2"},"schema":{"schema-version":"v2.2","dd-service":"tf-testaccdatadogservicedefinition_basicv2_2-local-1696619239","team":"my-team","contacts":[{"name":"Team Email","type":"email","contact":"[email protected]"}],"links":[{"name":"Architecture","type":"doc","provider":"Gigoogle drivetHub","url":"https://my-runbook"},{"name":"Runbook","type":"runbook","url":"https://my-runbook"},{"name":"Source Code","type":"repo","provider":"GitHub","url":"https://github.com/DataDog/schema"}],"tags":["my:tag","service:tag"],"integrations":{"pagerduty":{"service-url":"https://my-org.pagerduty.com/service-directory/PMyService"},"opsgenie":{"service-url":"https://my-org.opsgenie.com/service/123e4567-e89b-12d3-a456-426614174000","region":"US"}},"extensions":{"myorgextension":"extensionvalue"},"service-type":"web","languages":["go","python"]}}}}
headers:
Content-Type:
- application/json
status: 200 OK
code: 200
duration: ""
61 changes: 61 additions & 0 deletions datadog/tests/resource_datadog_service_definition_yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,25 @@ func TestAccDatadogServiceDefinition_BasicV2_1(t *testing.T) {
})
}

func TestAccDatadogServiceDefinition_BasicV2_2(t *testing.T) {
t.Parallel()
ctx, accProviders := testAccProviders(context.Background(), t)
uniq := strings.ToLower(uniqueEntityName(ctx, t))
accProvider := testAccProvider(t, accProviders)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: accProviders,
CheckDestroy: testAccCheckDatadogServiceDefinitionDestroy(accProvider),
Steps: []resource.TestStep{
{
Config: testAccCheckDatadogServiceDefinitionV2_2(uniq),
Check: checkServiceDefinitionExists(accProvider),
},
},
})
}

func TestAccDatadogServiceDefinition_BasicBackstage(t *testing.T) {
t.Parallel()
ctx, accProviders := testAccProviders(context.Background(), t)
Expand Down Expand Up @@ -156,6 +175,48 @@ EOF
}`, uniq)
}

func testAccCheckDatadogServiceDefinitionV2_2(uniq string) string {
return fmt.Sprintf(`
resource "datadog_service_definition_yaml" "service_definition" {
service_definition =<<EOF
schema-version: v2.2
dd-service: %s
contacts:
- contact: [email protected]
name: Team Email
type: email
extensions:
myorgextension: extensionvalue
integrations:
opsgenie:
region: US
service-url: https://my-org.opsgenie.com/service/123e4567-e89b-12d3-a456-426614174000
pagerduty:
service-url: https://my-org.pagerduty.com/service-directory/PMyService
links:
- name: Architecture
type: doc
provider: Gigoogle drivetHub
url: https://my-runbook
- name: Runbook
type: runbook
url: https://my-runbook
- name: Source Code
type: repo
provider: GitHub
url: https://github.com/DataDog/schema
tags:
- my:tag
- service:tag
team: my-team
languages:
- go
- python
service-type: web
EOF
}`, uniq)
}

func testAccCheckDatadogServiceDefinitionBackstage(uniq string) string {
return fmt.Sprintf(`
resource "datadog_service_definition_yaml" "service_definition_backstage" {
Expand Down
49 changes: 49 additions & 0 deletions docs/resources/service_definition_yaml.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,55 @@ Provides a Datadog service definition resource. This can be used to create and m
## Example Usage

```terraform
// Service Definition with v2.2 Schema Definition
resource "datadog_service_definition_yaml" "service_definition_v2_1" {
service_definition = <<EOF
schema-version: v2.2
dd-service: shopping-cart
team: e-commerce-team
contacts:
- name: Support Email
type: email
contact: [email protected]
- name: Support Slack
type: slack
contact: https://www.slack.com/archives/shopping-cart
description: shopping cart service responsible for managing shopping carts
tier: high
lifecycle: production
application: e-commerce
languages:
- go
- python
service-type: web
links:
- name: shopping-cart runbook
type: runbook
url: https://runbook/shopping-cart
- name: shopping-cart architecture
type: doc
provider: gdoc
url: https://google.drive/shopping-cart-architecture
- name: shopping-cart service Wiki
type: doc
provider: wiki
url: https://wiki/shopping-cart
- name: shopping-cart source code
type: repo
provider: github
url: http://github/shopping-cart
tags:
- business-unit:retail
- cost-center:engineering
integrations:
pagerduty:
service-url: https://www.pagerduty.com/service-directory/Pshopping-cart
extensions:
mycompany.com/shopping-cart:
customField: customValue
EOF
}

// Service Definition with v2.1 Schema Definition
resource "datadog_service_definition_yaml" "service_definition_v2_1" {
service_definition = <<EOF
Expand Down
49 changes: 49 additions & 0 deletions examples/resources/datadog_service_definition_yaml/resource.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,52 @@
// Service Definition with v2.2 Schema Definition
resource "datadog_service_definition_yaml" "service_definition_v2_1" {
service_definition = <<EOF
schema-version: v2.2
dd-service: shopping-cart
team: e-commerce-team
contacts:
- name: Support Email
type: email
contact: [email protected]
- name: Support Slack
type: slack
contact: https://www.slack.com/archives/shopping-cart
description: shopping cart service responsible for managing shopping carts
tier: high
lifecycle: production
application: e-commerce
languages:
- go
- python
service-type: web
links:
- name: shopping-cart runbook
type: runbook
url: https://runbook/shopping-cart
- name: shopping-cart architecture
type: doc
provider: gdoc
url: https://google.drive/shopping-cart-architecture
- name: shopping-cart service Wiki
type: doc
provider: wiki
url: https://wiki/shopping-cart
- name: shopping-cart source code
type: repo
provider: github
url: http://github/shopping-cart
tags:
- business-unit:retail
- cost-center:engineering
integrations:
pagerduty:
service-url: https://www.pagerduty.com/service-directory/Pshopping-cart
extensions:
mycompany.com/shopping-cart:
customField: customValue
EOF
}

// Service Definition with v2.1 Schema Definition
resource "datadog_service_definition_yaml" "service_definition_v2_1" {
service_definition = <<EOF
Expand Down