Skip to content
Open
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a3f6d71
Add SendUserProvidedResourceTags to third party integrations resource
marcabreracast Jul 25, 2025
4a1b71f
chore: Bump on-headers and compression in /examples/quickstart-mongod…
dependabot[bot] Jul 21, 2025
77f3db7
chore: Updates Atlas Go SDK (#1360)
svc-apix-Bot Jul 21, 2025
818a572
chore: Bump form-data from 4.0.3 to 4.0.4 in /examples/quickstart-mon…
dependabot[bot] Jul 22, 2025
611d1ea
chore: Bump marocchino/sticky-pull-request-comment from 2.9.3 to 2.9.…
dependabot[bot] Jul 22, 2025
0cb3c62
chore: Bump github.com/aws/aws-sdk-go-v2/config from 1.29.17 to 1.29.…
dependabot[bot] Jul 22, 2025
08f26be
chore: Bump github.com/aws/smithy-go from 1.22.4 to 1.22.5 in /cfn-re…
dependabot[bot] Jul 29, 2025
fb29074
chore: Bump github.com/aws/aws-sdk-go-v2 from 1.36.6 to 1.37.0 in /cf…
dependabot[bot] Jul 29, 2025
e7ff021
chore: Bump github.com/aws/aws-sdk-go-v2/service/cloudformation from …
dependabot[bot] Jul 29, 2025
3f7cf7a
chore: Bump github.com/aws/aws-sdk-go-v2/config from 1.29.18 to 1.30.…
dependabot[bot] Jul 29, 2025
f3500d8
chore: Bump tmp and @angular/cli in /examples/quickstart-mongodb-atla…
dependabot[bot] Aug 7, 2025
820e36c
chore: Bump github.com/aws/aws-sdk-go-v2/config from 1.30.0 to 1.30.3…
dependabot[bot] Aug 7, 2025
7594d26
chore: Bump aws-actions/configure-aws-credentials from 4.2.1 to 4.3.1…
dependabot[bot] Aug 7, 2025
c1e6818
chore: Bump github.com/aws/aws-sdk-go-v2 from 1.37.2 to 1.38.0 in /cf…
dependabot[bot] Aug 12, 2025
7e75bc7
chore: Bump bewuethr/shellcheck-action from 2.2.0 to 2.3.0 (#1404)
dependabot[bot] Aug 13, 2025
6391ce0
chore: Bump github.com/aws/aws-sdk-go-v2/service/cloudformation from …
dependabot[bot] Aug 13, 2025
6aabe73
Fix compilation issue for integrations results due to SDK update
marcabreracast Aug 18, 2025
f1df94b
Add config file from cfn generate
marcabreracast Aug 18, 2025
b60ae36
Remove copyright when running cfn generate
marcabreracast Aug 18, 2025
caa319d
Remove Scheme field in order to match deprecation of the field due to…
marcabreracast Aug 19, 2025
68fc3ac
Additional checks for new field addition, in order to preserve attrib…
marcabreracast Aug 19, 2025
00204a7
Merge branch 'master' into CLOUDP-327113_ThirdPartyIntegration_AddRes…
marcabreracast Aug 19, 2025
8bb5fc9
Add inputs for contract tests on new field
marcabreracast Aug 20, 2025
d47e43b
Remove Scheme instances from deprecated attribute
marcabreracast Aug 20, 2025
2e1f8c7
Remove deprecated Scheme field from custom validation
marcabreracast Aug 20, 2025
881a029
Address PR review comments
marcabreracast Aug 22, 2025
6263d62
Perform additional cfn generate
marcabreracast Aug 22, 2025
36e955b
Address PR comments
marcabreracast Aug 22, 2025
209e1eb
Remove extra check
marcabreracast Aug 22, 2025
b915df6
Amend check in order to avoid panic error
marcabreracast Aug 22, 2025
8a5a721
Update example
marcabreracast Aug 22, 2025
153553d
Merge branch 'master' into CLOUDP-327113_ThirdPartyIntegration_AddRes…
marcabreracast Aug 22, 2025
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
14 changes: 0 additions & 14 deletions cfn-resources/third-party-integration/cmd/main.go

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

19 changes: 19 additions & 0 deletions cfn-resources/third-party-integration/cmd/resource/config.go

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

54 changes: 20 additions & 34 deletions cfn-resources/third-party-integration/cmd/resource/model.go

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

64 changes: 39 additions & 25 deletions cfn-resources/third-party-integration/cmd/resource/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
log "github.com/mongodb/mongodbatlas-cloudformation-resources/util/logger"
"github.com/mongodb/mongodbatlas-cloudformation-resources/util/progressevent"
"github.com/mongodb/mongodbatlas-cloudformation-resources/util/validator"
"go.mongodb.org/atlas-sdk/v20231115002/admin"
"go.mongodb.org/atlas-sdk/v20250312005/admin"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This update is needed in order to implement SendUserProvidedResourceTags field.

)

var RequiredFields = []string{constants.IntegrationType, constants.ProjectID}
Expand All @@ -41,7 +41,7 @@ var requiredPerType = map[string][]string{
"FLOWDOCK": {"FlowName", "ApiToken", "OrgName"},
"WEBHOOK": {"Url"},
"MICROSOFT_TEAMS": {"MicrosoftTeamsWebhookUrl"},
"PROMETHEUS": {"UserName", "Password", "ServiceDiscovery", "Scheme", "Enabled"},
"PROMETHEUS": {"UserName", "Password", "ServiceDiscovery", "Enabled"},
}

func validateModel(fields []string, model *Model) *handler.ProgressEvent {
Expand Down Expand Up @@ -76,18 +76,23 @@ func Create(req handler.Request, prevModel *Model, currentModel *Model) (handler
}

requestBody := modelToIntegration(currentModel)
integrations, resModel, err := client.Atlas20231115002.ThirdPartyIntegrationsApi.CreateThirdPartyIntegration(context.Background(), *IntegrationType, *ProjectID, requestBody).Execute()
integrations, resModel, err := client.AtlasSDK.ThirdPartyIntegrationsApi.CreateThirdPartyIntegration(context.Background(), *IntegrationType, *ProjectID, requestBody).Execute()
if err != nil {
if apiError, ok := admin.AsError(err); ok && *apiError.Error == http.StatusConflict {
if apiError, ok := admin.AsError(err); ok && apiError.Error == http.StatusConflict {
Copy link

Copilot AI Aug 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comparison apiError.Error == http.StatusConflict is incorrect. apiError.Error is likely an integer status code, but http.StatusConflict is also an integer (409). However, the comparison should use *apiError.ErrorCode or similar field that contains the HTTP status code, not apiError.Error directly.

Suggested change
if apiError, ok := admin.AsError(err); ok && apiError.Error == http.StatusConflict {
if apiError, ok := admin.AsError(err); ok && apiError.ErrorCode == http.StatusConflict {

Copilot uses AI. Check for mistakes.

return progressevent.GetFailedEventByCode("INTEGRATION_ALREADY_CONFIGURED.", cloudformation.HandlerErrorCodeAlreadyExists), nil
}

return progressevent.GetFailedEventByResponse(err.Error(), resModel), nil
}

if integrations == nil || len(integrations.GetResults()) == 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if integrations == nil || len(integrations.GetResults()) == 0 {
if len(integrations.GetResults()) == 0 {

no need to check integration is not nil, see GetResults implementation:

func (o *PaginatedIntegration) GetResults() []ThirdPartyIntegration {
	if o == nil || IsNil(o.Results) {
		var ret []ThirdPartyIntegration
		return ret
	}
	return *o.Results
}

same for the other ocurrence

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in fact, as you're using results later, instead of retrieving again, you can do something like:

   results := integrations.GetResults()
   if len(results) == 0 {
		return progressevent.GetFailedEventByResponse("No integration returned from create", resModel), nil
	}

	return handler.ProgressEvent{
		OperationStatus: handler.Success,
		ResourceModel:   integrationToModel(*currentModel, &results[0]),
	}, nil

return progressevent.GetFailedEventByResponse("No integration returned from create", resModel), nil
}

results := integrations.GetResults()
return handler.ProgressEvent{
OperationStatus: handler.Success,
ResourceModel: integrationToModel(*currentModel, &integrations.Results[0]),
ResourceModel: integrationToModel(*currentModel, &results[0]),
}, nil
}

Expand All @@ -108,7 +113,7 @@ func Read(req handler.Request, prevModel *Model, currentModel *Model) (handler.P
ProjectID := currentModel.ProjectId
IntegrationType := currentModel.Type

integration, res, err := client.Atlas20231115002.ThirdPartyIntegrationsApi.GetThirdPartyIntegration(context.Background(), *ProjectID, *IntegrationType).Execute()
integration, res, err := client.AtlasSDK.ThirdPartyIntegrationsApi.GetThirdPartyIntegration(context.Background(), *ProjectID, *IntegrationType).Execute()

if err != nil {
return progressevent.GetFailedEventByResponse(err.Error(), res), nil
Expand Down Expand Up @@ -139,24 +144,29 @@ func Update(req handler.Request, prevModel *Model, currentModel *Model) (handler
ProjectID := currentModel.ProjectId
IntegrationType := currentModel.Type

integration, res, err := client.Atlas20231115002.ThirdPartyIntegrationsApi.GetThirdPartyIntegration(context.Background(), *ProjectID, *IntegrationType).Execute()
integration, res, err := client.AtlasSDK.ThirdPartyIntegrationsApi.GetThirdPartyIntegration(context.Background(), *ProjectID, *IntegrationType).Execute()
if err != nil {
return progressevent.GetFailedEventByResponse(err.Error(), res), nil
}

updateIntegrationFromSchema(currentModel, integration)
integrations, res, err := client.Atlas20231115002.ThirdPartyIntegrationsApi.UpdateThirdPartyIntegration(context.Background(), *IntegrationType, *ProjectID, integration).Execute()
integrations, res, err := client.AtlasSDK.ThirdPartyIntegrationsApi.UpdateThirdPartyIntegration(context.Background(), *IntegrationType, *ProjectID, integration).Execute()
if err != nil {
return progressevent.GetFailedEventByResponse(err.Error(), res), nil
}

if integrations == nil || len(integrations.GetResults()) == 0 {
return progressevent.GetFailedEventByResponse("No integration returned from update", res), nil
}

results := integrations.GetResults()
return handler.ProgressEvent{
OperationStatus: handler.Success,
ResourceModel: integrationToModel(*currentModel, &integrations.Results[0]),
ResourceModel: integrationToModel(*currentModel, &results[0]),
}, nil
}

func updateIntegrationFromSchema(currentModel *Model, integration *admin.ThridPartyIntegration) {
func updateIntegrationFromSchema(currentModel *Model, integration *admin.ThirdPartyIntegration) {
if util.IsStringPresent(currentModel.Url) && !util.AreStringPtrEqual(currentModel.Url, integration.Url) {
integration.Url = currentModel.Url
}
Expand Down Expand Up @@ -196,12 +206,13 @@ func updateIntegrationFromSchema(currentModel *Model, integration *admin.ThridPa
if util.IsStringPresent(currentModel.ServiceDiscovery) && !util.AreStringPtrEqual(currentModel.ServiceDiscovery, integration.ServiceDiscovery) {
integration.ServiceDiscovery = currentModel.ServiceDiscovery
}
if util.IsStringPresent(currentModel.Scheme) && !util.AreStringPtrEqual(currentModel.Scheme, integration.Scheme) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scheme field attribute is removed in more recent versions of the SDK. See this Terraform PR where this same field is removed and is addressed as a breaking change.

integration.Scheme = currentModel.Scheme
}
if currentModel.Enabled != nil && currentModel.Enabled != integration.Enabled {
integration.Enabled = currentModel.Enabled
}

if currentModel.SendUserProvidedResourceTags != nil {
integration.SendUserProvidedResourceTags = currentModel.SendUserProvidedResourceTags
}
}

func Delete(req handler.Request, prevModel *Model, currentModel *Model) (handler.ProgressEvent, error) {
Expand All @@ -223,7 +234,7 @@ func Delete(req handler.Request, prevModel *Model, currentModel *Model) (handler
ProjectID := currentModel.ProjectId
IntegrationType := currentModel.Type

_, res, err = client.Atlas20231115002.ThirdPartyIntegrationsApi.DeleteThirdPartyIntegration(context.Background(), *IntegrationType, *ProjectID).Execute()
res, err = client.AtlasSDK.ThirdPartyIntegrationsApi.DeleteThirdPartyIntegration(context.Background(), *IntegrationType, *ProjectID).Execute()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why define vars res and err separated instead of using := here?

res, err := client.AtlasSDK.ThirdPartyIntegrationsApi.DeleteThirdPartyIntegration(context.Background(), *IntegrationType, *ProjectID).Execute()


if err != nil {
return progressevent.GetFailedEventByResponse(err.Error(), res), nil
Expand Down Expand Up @@ -251,15 +262,18 @@ func List(req handler.Request, prevModel *Model, currentModel *Model) (handler.P

var res *http.Response
ProjectID := currentModel.ProjectId
integrations, res, err := client.Atlas20231115002.ThirdPartyIntegrationsApi.ListThirdPartyIntegrations(context.Background(), *ProjectID).Execute()
integrations, res, err := client.AtlasSDK.ThirdPartyIntegrationsApi.ListThirdPartyIntegrations(context.Background(), *ProjectID).Execute()
if err != nil {
return progressevent.GetFailedEventByResponse(err.Error(), res), nil
}

mm := make([]interface{}, 0)
for i := range integrations.Results {
m := integrationToModel(*currentModel, &integrations.Results[i])
mm = append(mm, m)
if integrations == nil || len(integrations.GetResults()) == 0 {
results := integrations.GetResults()
for i := range results {
m := integrationToModel(*currentModel, &results[i])
mm = append(mm, m)
}
}

// Response
Expand All @@ -270,18 +284,15 @@ func List(req handler.Request, prevModel *Model, currentModel *Model) (handler.P
}, nil
}

func modelToIntegration(currentModel *Model) (out *admin.ThridPartyIntegration) {
out = &admin.ThridPartyIntegration{}
func modelToIntegration(currentModel *Model) (out *admin.ThirdPartyIntegration) {
out = &admin.ThirdPartyIntegration{}

if util.IsStringPresent(currentModel.Type) {
out.Type = currentModel.Type
}
if currentModel.Enabled != nil {
out.Enabled = currentModel.Enabled
}
if util.IsStringPresent(currentModel.Scheme) {
out.Scheme = currentModel.Scheme
}
if util.IsStringPresent(currentModel.ServiceDiscovery) {
out.ServiceDiscovery = currentModel.ServiceDiscovery
}
Expand Down Expand Up @@ -321,11 +332,13 @@ func modelToIntegration(currentModel *Model) (out *admin.ThridPartyIntegration)
if util.IsStringPresent(currentModel.ApiKey) {
out.ApiKey = currentModel.ApiKey
}

if currentModel.SendUserProvidedResourceTags != nil {
out.SendUserProvidedResourceTags = currentModel.SendUserProvidedResourceTags
}
return out
}

func integrationToModel(currentModel Model, integration *admin.ThridPartyIntegration) Model {
func integrationToModel(currentModel Model, integration *admin.ThirdPartyIntegration) Model {
// if "Enabled" is not set in the inputs we dont want to return "Enabled" in outputs
enabled := currentModel.Enabled != nil

Expand All @@ -341,5 +354,6 @@ func integrationToModel(currentModel Model, integration *admin.ThridPartyIntegra
if !enabled {
out.Enabled = nil
}

return out
}
32 changes: 15 additions & 17 deletions cfn-resources/third-party-integration/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ To declare this entity in your AWS CloudFormation template, use the following sy
"<a href="#username" title="UserName">UserName</a>" : <i>String</i>,
"<a href="#password" title="Password">Password</a>" : <i>String</i>,
"<a href="#servicediscovery" title="ServiceDiscovery">ServiceDiscovery</a>" : <i>String</i>,
"<a href="#scheme" title="Scheme">Scheme</a>" : <i>String</i>,
"<a href="#enabled" title="Enabled">Enabled</a>" : <i>Boolean</i>,
"<a href="#listenaddress" title="ListenAddress">ListenAddress</a>" : <i>String</i>,
"<a href="#tlspempath" title="TlsPemPath">TlsPemPath</a>" : <i>String</i>
"<a href="#tlspempath" title="TlsPemPath">TlsPemPath</a>" : <i>String</i>,
"<a href="#senduserprovidedresourcetags" title="SendUserProvidedResourceTags">SendUserProvidedResourceTags</a>" : <i>Boolean</i>
}
}
</pre>
Expand All @@ -57,10 +57,10 @@ Properties:
<a href="#username" title="UserName">UserName</a>: <i>String</i>
<a href="#password" title="Password">Password</a>: <i>String</i>
<a href="#servicediscovery" title="ServiceDiscovery">ServiceDiscovery</a>: <i>String</i>
<a href="#scheme" title="Scheme">Scheme</a>: <i>String</i>
<a href="#enabled" title="Enabled">Enabled</a>: <i>Boolean</i>
<a href="#listenaddress" title="ListenAddress">ListenAddress</a>: <i>String</i>
<a href="#tlspempath" title="TlsPemPath">TlsPemPath</a>: <i>String</i>
<a href="#senduserprovidedresourcetags" title="SendUserProvidedResourceTags">SendUserProvidedResourceTags</a>: <i>Boolean</i>
</pre>

## Properties
Expand All @@ -69,7 +69,7 @@ Properties:

Unique 24-hexadecimal digit string that identifies your project.

_Required_: No
_Required_: Yes

_Type_: String

Expand All @@ -89,7 +89,7 @@ _Update requires_: [Replacement](https://docs.aws.amazon.com/AWSCloudFormation/l

Human-readable label that identifies the service to which you want to integrate with MongoDB Cloud. The value must match the third-party service integration type.

_Required_: No
_Required_: Yes

_Type_: String

Expand Down Expand Up @@ -229,18 +229,6 @@ _Allowed Values_: <code>http</code> | <code>file</code>

_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)

#### Scheme

Security Scheme to apply to HyperText Transfer Protocol (HTTP) traffic between Prometheus and MongoDB Cloud.

_Required_: No

_Type_: String

_Allowed Values_: <code>http</code> | <code>https</code>

_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)

#### Enabled

Flag that indicates whether someone has activated the Prometheus integration.
Expand Down Expand Up @@ -271,3 +259,13 @@ _Type_: String

_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)

#### SendUserProvidedResourceTags

Flag that indicates whether to include user-defined resource tags when sending metrics and alerts to third-party services.

_Required_: No

_Type_: Boolean

_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)

Loading
Loading