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

ENG-12679: Add data source for sidecar instance API #457

Merged
merged 7 commits into from
Oct 2, 2023
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ make docker-compose/docs
pre-commit run --show-diff-on-failure --color=always --all-files
```

> **_Note_** that due to a [limitation of the tfplugindocs tool](https://github.com/hashicorp/terraform-plugin-docs/issues/28), some descriptions might not be automatically generated for nested fields. In this case, its necessary to generate the documentation manually by editing the template file - in the `templates` folder - corresponding to the resource/data-source.

> `pre-commit` can sometimes fail because your user is not the owner of the files in the `/docs` directory.
> To solve this problem, run the following command and re-run the `pre-commit run...` tried in the previous step:

Expand Down
196 changes: 196 additions & 0 deletions cyral/data_source_cyral_sidecar_instance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
package cyral

import (
"fmt"
"net/http"

"github.com/cyralinc/terraform-provider-cyral/client"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

const (
// Schema keys
SidecarInstanceListKey = "instance_list"
MetadataKey = "metadata"
MonitoringKey = "monitoring"
VersionKey = "version"
DynamicVersionKey = "dynamic_version"
CapabilitiesKey = "capabilities"
StartTimestampKey = "start_timestamp"
LastRegistrationKey = "last_registration"
RecyclingKey = "recycling"
RecyclableKey = "recyclable"
ServicesKey = "services"
MetricsPortKey = "metrics_port"
ComponentsKey = "components"
ErrorKey = "error"
)

func dataSourceSidecarInstance() *schema.Resource {
return &schema.Resource{
Description: "Retrieve sidecar instances.",
ReadContext: ReadResource(ResourceOperationConfig{
Name: "SidecarInstanceDataSourceRead",
HttpMethod: http.MethodGet,
CreateURL: func(d *schema.ResourceData, c *client.Client) string {
return fmt.Sprintf(
"https://%s/v2/sidecars/%s/instances",
c.ControlPlane, d.Get(SidecarIDKey),
)
},
NewResponseData: func(_ *schema.ResourceData) ResponseData {
return &SidecarInstances{}
},
}),
Schema: map[string]*schema.Schema{
SidecarIDKey: {
Description: "Sidecar identifier.",
Type: schema.TypeString,
Required: true,
},
IDKey: {
Description: "Data source identifier.",
Type: schema.TypeString,
Computed: true,
},
SidecarInstanceListKey: {
Description: "List of existing sidecar instances.",
Computed: true,
Type: schema.TypeList,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
IDKey: {
Description: "Instance identifier. Varies according to the computing platform that " +
"the sidecar is deployed to.",
Type: schema.TypeString,
Computed: true,
},
MetadataKey: {
Description: "Instance metadata.",
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
VersionKey: {
Description: "Sidecar version that the instance is using.",
Type: schema.TypeString,
Computed: true,
},
DynamicVersionKey: {
Description: "If true, indicates that the instance has dynamic versioning, " +
"that means that the version is not fixed at template level and it can be " +
"automatically upgraded.",
Type: schema.TypeBool,
Computed: true,
},
CapabilitiesKey: {
Description: "Set of capabilities that can be enabled or disabled. **Note**: This " +
"field is per-instance, not per-sidecar, because not all sidecar instances might be " +
"in sync at some point in time.",
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
RecyclableKey: {
Description: "Indicates if sidecar instance will be recycled (e.g., by an ASG) " +
"if it reports itself as unhealthy.",
Type: schema.TypeBool,
Computed: true,
},
},
},
},
StartTimestampKey: {
Description: "The time when the instance started.",
Type: schema.TypeString,
Computed: true,
},
LastRegistrationKey: {
Description: "The last time the instance reported to the Control Plane.",
Type: schema.TypeString,
Computed: true,
},
RecyclingKey: {
Description: "Indicates whether the Control Plane has asked the instance to mark " +
"itself unhealthy so that it is recycled by the infrastructure.",
Type: schema.TypeBool,
Computed: true,
},
},
},
},
MonitoringKey: {
Description: "Instance monitoring information, such as its overall health.",
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
StatusKey: {
Description: "Aggregated status of all the sidecar services.",
Type: schema.TypeString,
Computed: true,
},
ServicesKey: {
Description: "Sidecar instance services monitoring information.",
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeSet,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
StatusKey: {
Description: "Aggregated status of sidecar service.",
Type: schema.TypeString,
Computed: true,
},
MetricsPortKey: {
Description: "Metrics port for service monitoring.",
Type: schema.TypeInt,
Computed: true,
},
ComponentsKey: {
Description: "Map of name to monitoring component. A component is a " +
"monitored check on the service that has its own status.",
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeSet,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
StatusKey: {
Description: "Component status.",
Type: schema.TypeString,
Computed: true,
},
DescriptionKey: {
Description: "Describes what the type of check the component represents.",
Type: schema.TypeString,
Computed: true,
},
ErrorKey: {
Description: "Error that describes what caused the current status.",
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
HostKey: {
Description: "Service host on the deployment.",
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
},
},
},
},
},
},
},
}
}
6 changes: 4 additions & 2 deletions cyral/data_source_cyral_sidecar_instance_ids.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@ import (
)

type SidecarDetails struct {
Instances []SidecarInstance `json:"instances,omitempty"`
Instances []DeprecatedSidecarInstances `json:"instances,omitempty"`
}

type SidecarInstance struct {
type DeprecatedSidecarInstances struct {
ASGInstanceID string `json:"asg_instance,omitempty"`
}

func dataSourceSidecarInstanceIDs() *schema.Resource {
return &schema.Resource{
DeprecationMessage: "This data source was deprecated. It will be removed in the next major version of " +
"the provider. Use the data source `cyral_sidecar_instance` instead",
Description: "Retrieves the IDs of all the current instances of a given sidecar.",
ReadContext: dataSourceSidecarInstanceIDsRead,
Schema: map[string]*schema.Schema{
Expand Down
88 changes: 88 additions & 0 deletions cyral/data_source_cyral_sidecar_instance_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package cyral

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

const (
sidecarInstanceDataSourceFullNameFmt = "data.cyral_sidecar_instance.%s"
)

func TestAccSidecarInstanceDataSource(t *testing.T) {
dataSourceName := "instances"
testSteps := []resource.TestStep{
accTestStepSidecarInstanceDataSource_EmptySidecarID(dataSourceName),
accTestStepSidecarInstanceDataSource_NoSidecarFoundForGivenID(dataSourceName),
accTestStepSidecarInstanceDataSource_NoSidecarInstances(dataSourceName),
}
resource.ParallelTest(
t, resource.TestCase{
ProviderFactories: providerFactories,
Steps: testSteps,
},
)
}

func accTestStepSidecarInstanceDataSource_EmptySidecarID(dataSourceName string) resource.TestStep {
config := fmt.Sprintf(`
data "cyral_sidecar_instance" "%s" {
}
`, dataSourceName)
return resource.TestStep{
Config: config,
ExpectError: regexp.MustCompile(fmt.Sprintf(`The argument "%s" is required`, SidecarIDKey)),
}
}

func accTestStepSidecarInstanceDataSource_NoSidecarFoundForGivenID(dataSourceName string) resource.TestStep {
nonExistentSidecarID := "some-non-existent-sidecar-id"
config := fmt.Sprintf(`
data "cyral_sidecar_instance" "%s" {
sidecar_id = %q
}
`, dataSourceName, nonExistentSidecarID)
return resource.TestStep{
Config: config,
ExpectError: regexp.MustCompile(fmt.Sprintf("sidecar with id '%s' does not exist", nonExistentSidecarID)),
}
}

func accTestStepSidecarInstanceDataSource_NoSidecarInstances(dataSourceName string) resource.TestStep {
// Creates a sidecar that doesn't have any instances, since it was not
// deployed.
config := formatBasicSidecarIntoConfig(
basicSidecarResName,
accTestName("data-sidecar-instance", "sidecar"),
"cft-ec2",
"",
)
config += fmt.Sprintf(`
data "cyral_sidecar_instance" "%s" {
sidecar_id = %s
}
`, dataSourceName, basicSidecarID)
dataSourceFullName := fmt.Sprintf(sidecarInstanceDataSourceFullNameFmt, dataSourceName)
check := resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(
dataSourceFullName,
SidecarIDKey,
),
resource.TestCheckResourceAttrSet(
dataSourceFullName,
IDKey,
),
resource.TestCheckResourceAttr(
dataSourceFullName,
fmt.Sprintf("%s.#", SidecarInstanceListKey),
"0",
),
)
return resource.TestStep{
Config: config,
Check: check,
}
}
Loading
Loading