provider/aws: Add support for aws_ssm_maintenance_window (#14087)
* provider/aws: Add support for aws_ssm_maintenance_window Fixes: #14027 ``` % make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSSSMMaintenanceWindow_basic' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/04/29 13:38:19 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSSSMMaintenanceWindow_basic -timeout 120m === RUN TestAccAWSSSMMaintenanceWindow_basic --- PASS: TestAccAWSSSMMaintenanceWindow_basic (51.69s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 51.711s ``` * provider/aws: Add documentation for aws_ssm_maintenance_window * provider/aws: Add support for aws_ssm_maintenance_window_target ``` % make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSSSMMaintenanceWindowTarget' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/04/29 16:38:22 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSSSMMaintenanceWindowTarget -timeout 120m === RUN TestAccAWSSSMMaintenanceWindowTarget_basic --- PASS: TestAccAWSSSMMaintenanceWindowTarget_basic (34.68s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 34.701s ``` * provider/aws: Adding the documentation for aws_ssm_maintenance_window_target * provider/aws: Add support for aws_ssm_maintenance_window_task * provider/aws: Documentation for aws_ssm_maintenance_window_task
This commit is contained in:
parent
3fe6b536ff
commit
e18f8df845
|
@ -422,6 +422,9 @@ func Provider() terraform.ResourceProvider {
|
|||
"aws_ssm_activation": resourceAwsSsmActivation(),
|
||||
"aws_ssm_association": resourceAwsSsmAssociation(),
|
||||
"aws_ssm_document": resourceAwsSsmDocument(),
|
||||
"aws_ssm_maintenance_window": resourceAwsSsmMaintenanceWindow(),
|
||||
"aws_ssm_maintenance_window_target": resourceAwsSsmMaintenanceWindowTarget(),
|
||||
"aws_ssm_maintenance_window_task": resourceAwsSsmMaintenanceWindowTask(),
|
||||
"aws_spot_datafeed_subscription": resourceAwsSpotDataFeedSubscription(),
|
||||
"aws_spot_instance_request": resourceAwsSpotInstanceRequest(),
|
||||
"aws_spot_fleet_request": resourceAwsSpotFleetRequest(),
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ssm"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func resourceAwsSsmMaintenanceWindow() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceAwsSsmMaintenanceWindowCreate,
|
||||
Read: resourceAwsSsmMaintenanceWindowRead,
|
||||
Update: resourceAwsSsmMaintenanceWindowUpdate,
|
||||
Delete: resourceAwsSsmMaintenanceWindowDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"schedule": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"duration": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"cutoff": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"allow_unassociated_targets": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: false,
|
||||
},
|
||||
|
||||
"enabled": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceAwsSsmMaintenanceWindowCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
ssmconn := meta.(*AWSClient).ssmconn
|
||||
|
||||
params := &ssm.CreateMaintenanceWindowInput{
|
||||
Name: aws.String(d.Get("name").(string)),
|
||||
Schedule: aws.String(d.Get("schedule").(string)),
|
||||
Duration: aws.Int64(int64(d.Get("duration").(int))),
|
||||
Cutoff: aws.Int64(int64(d.Get("cutoff").(int))),
|
||||
AllowUnassociatedTargets: aws.Bool(d.Get("allow_unassociated_targets").(bool)),
|
||||
}
|
||||
|
||||
resp, err := ssmconn.CreateMaintenanceWindow(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.SetId(*resp.WindowId)
|
||||
|
||||
return resourceAwsSsmMaintenanceWindowRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsSsmMaintenanceWindowUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
ssmconn := meta.(*AWSClient).ssmconn
|
||||
|
||||
params := &ssm.UpdateMaintenanceWindowInput{
|
||||
WindowId: aws.String(d.Id()),
|
||||
}
|
||||
|
||||
if d.HasChange("name") {
|
||||
params.Name = aws.String(d.Get("name").(string))
|
||||
}
|
||||
|
||||
if d.HasChange("schedule") {
|
||||
params.Schedule = aws.String(d.Get("schedule").(string))
|
||||
}
|
||||
|
||||
if d.HasChange("duration") {
|
||||
params.Duration = aws.Int64(int64(d.Get("duration").(int)))
|
||||
}
|
||||
|
||||
if d.HasChange("cutoff") {
|
||||
params.Cutoff = aws.Int64(int64(d.Get("cutoff").(int)))
|
||||
}
|
||||
|
||||
if d.HasChange("allow_unassociated_targets") {
|
||||
params.AllowUnassociatedTargets = aws.Bool(d.Get("allow_unassociated_targets").(bool))
|
||||
}
|
||||
|
||||
if d.HasChange("enabled") {
|
||||
params.Enabled = aws.Bool(d.Get("enabled").(bool))
|
||||
}
|
||||
|
||||
_, err := ssmconn.UpdateMaintenanceWindow(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resourceAwsSsmMaintenanceWindowRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsSsmMaintenanceWindowRead(d *schema.ResourceData, meta interface{}) error {
|
||||
ssmconn := meta.(*AWSClient).ssmconn
|
||||
|
||||
params := &ssm.DescribeMaintenanceWindowsInput{
|
||||
Filters: []*ssm.MaintenanceWindowFilter{
|
||||
{
|
||||
Key: aws.String("Name"),
|
||||
Values: []*string{aws.String(d.Get("name").(string))},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := ssmconn.DescribeMaintenanceWindows(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
found := false
|
||||
|
||||
for _, window := range resp.WindowIdentities {
|
||||
if *window.WindowId == d.Id() {
|
||||
found = true
|
||||
|
||||
d.Set("name", window.Name)
|
||||
d.Set("cutoff", window.Cutoff)
|
||||
d.Set("duration", window.Duration)
|
||||
d.Set("enabled", window.Enabled)
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
log.Printf("[INFO] Cannot find the SSM Maintenance Window %q. Removing from state", d.Get("name").(string))
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsSsmMaintenanceWindowDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
ssmconn := meta.(*AWSClient).ssmconn
|
||||
|
||||
log.Printf("[INFO] Deleting SSM Maintenance Window: %s", d.Id())
|
||||
|
||||
params := &ssm.DeleteMaintenanceWindowInput{
|
||||
WindowId: aws.String(d.Id()),
|
||||
}
|
||||
|
||||
_, err := ssmconn.DeleteMaintenanceWindow(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ssm"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func resourceAwsSsmMaintenanceWindowTarget() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceAwsSsmMaintenanceWindowTargetCreate,
|
||||
Read: resourceAwsSsmMaintenanceWindowTargetRead,
|
||||
Delete: resourceAwsSsmMaintenanceWindowTargetDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"window_id": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"resource_type": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"targets": {
|
||||
Type: schema.TypeList,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
MaxItems: 1,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"key": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"values": {
|
||||
Type: schema.TypeList,
|
||||
Required: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"owner_information": {
|
||||
Type: schema.TypeString,
|
||||
ForceNew: true,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func expandAwsSsmMaintenanceWindowTargets(d *schema.ResourceData) []*ssm.Target {
|
||||
var targets []*ssm.Target
|
||||
|
||||
targetConfig := d.Get("targets").([]interface{})
|
||||
|
||||
for _, tConfig := range targetConfig {
|
||||
config := tConfig.(map[string]interface{})
|
||||
|
||||
target := &ssm.Target{
|
||||
Key: aws.String(config["key"].(string)),
|
||||
Values: expandStringList(config["values"].([]interface{})),
|
||||
}
|
||||
|
||||
targets = append(targets, target)
|
||||
}
|
||||
|
||||
return targets
|
||||
}
|
||||
|
||||
func flattenAwsSsmMaintenanceWindowTargets(targets []*ssm.Target) []map[string]interface{} {
|
||||
if len(targets) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
result := make([]map[string]interface{}, 0, len(targets))
|
||||
target := targets[0]
|
||||
|
||||
t := make(map[string]interface{})
|
||||
t["key"] = *target.Key
|
||||
t["values"] = flattenStringList(target.Values)
|
||||
|
||||
result = append(result, t)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func resourceAwsSsmMaintenanceWindowTargetCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
ssmconn := meta.(*AWSClient).ssmconn
|
||||
|
||||
log.Printf("[INFO] Registering SSM Maintenance Window Target")
|
||||
|
||||
params := &ssm.RegisterTargetWithMaintenanceWindowInput{
|
||||
WindowId: aws.String(d.Get("window_id").(string)),
|
||||
ResourceType: aws.String(d.Get("resource_type").(string)),
|
||||
Targets: expandAwsSsmMaintenanceWindowTargets(d),
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("owner_information"); ok {
|
||||
params.OwnerInformation = aws.String(v.(string))
|
||||
}
|
||||
|
||||
resp, err := ssmconn.RegisterTargetWithMaintenanceWindow(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.SetId(*resp.WindowTargetId)
|
||||
|
||||
return resourceAwsSsmMaintenanceWindowTargetRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsSsmMaintenanceWindowTargetRead(d *schema.ResourceData, meta interface{}) error {
|
||||
ssmconn := meta.(*AWSClient).ssmconn
|
||||
|
||||
params := &ssm.DescribeMaintenanceWindowTargetsInput{
|
||||
WindowId: aws.String(d.Get("window_id").(string)),
|
||||
Filters: []*ssm.MaintenanceWindowFilter{
|
||||
{
|
||||
Key: aws.String("WindowTargetId"),
|
||||
Values: []*string{aws.String(d.Id())},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := ssmconn.DescribeMaintenanceWindowTargets(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, t := range resp.Targets {
|
||||
if *t.WindowTargetId == d.Id() {
|
||||
found = true
|
||||
|
||||
d.Set("owner_information", t.OwnerInformation)
|
||||
d.Set("window_id", t.WindowId)
|
||||
d.Set("resource_type", t.ResourceType)
|
||||
|
||||
if err := d.Set("targets", flattenAwsSsmMaintenanceWindowTargets(t.Targets)); err != nil {
|
||||
return fmt.Errorf("[DEBUG] Error setting targets error: %#v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
log.Printf("[INFO] Maintenance Window Target not found. Removing from state")
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsSsmMaintenanceWindowTargetDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
ssmconn := meta.(*AWSClient).ssmconn
|
||||
|
||||
log.Printf("[INFO] Deregistering SSM Maintenance Window Target: %s", d.Id())
|
||||
|
||||
params := &ssm.DeregisterTargetFromMaintenanceWindowInput{
|
||||
WindowId: aws.String(d.Get("window_id").(string)),
|
||||
WindowTargetId: aws.String(d.Id()),
|
||||
}
|
||||
|
||||
_, err := ssmconn.DeregisterTargetFromMaintenanceWindow(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/service/ssm"
|
||||
"github.com/hashicorp/terraform/helper/acctest"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccAWSSSMMaintenanceWindowTarget_basic(t *testing.T) {
|
||||
name := acctest.RandString(10)
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSSSMMaintenanceWindowTargetDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccAWSSSMMaintenanceWindowTargetBasicConfig(name),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSSSMMaintenanceWindowTargetExists("aws_ssm_maintenance_window_target.target"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckAWSSSMMaintenanceWindowTargetExists(n string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No SSM Maintenance Window Target Window ID is set")
|
||||
}
|
||||
|
||||
conn := testAccProvider.Meta().(*AWSClient).ssmconn
|
||||
|
||||
resp, err := conn.DescribeMaintenanceWindowTargets(&ssm.DescribeMaintenanceWindowTargetsInput{
|
||||
WindowId: aws.String(rs.Primary.Attributes["window_id"]),
|
||||
Filters: []*ssm.MaintenanceWindowFilter{
|
||||
{
|
||||
Key: aws.String("WindowTargetId"),
|
||||
Values: []*string{aws.String(rs.Primary.ID)},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, i := range resp.Targets {
|
||||
if *i.WindowTargetId == rs.Primary.ID {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("No AWS SSM Maintenance window target found")
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckAWSSSMMaintenanceWindowTargetDestroy(s *terraform.State) error {
|
||||
conn := testAccProvider.Meta().(*AWSClient).ssmconn
|
||||
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "aws_ssm_maintenance_window_target" {
|
||||
continue
|
||||
}
|
||||
|
||||
out, err := conn.DescribeMaintenanceWindowTargets(&ssm.DescribeMaintenanceWindowTargetsInput{
|
||||
WindowId: aws.String(rs.Primary.Attributes["window_id"]),
|
||||
Filters: []*ssm.MaintenanceWindowFilter{
|
||||
{
|
||||
Key: aws.String("WindowTargetId"),
|
||||
Values: []*string{aws.String(rs.Primary.ID)},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
// Verify the error is what we want
|
||||
if ae, ok := err.(awserr.Error); ok && ae.Code() == "DoesNotExistException" {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if len(out.Targets) > 0 {
|
||||
return fmt.Errorf("Expected AWS SSM Maintenance Target to be gone, but was still found")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func testAccAWSSSMMaintenanceWindowTargetBasicConfig(rName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_ssm_maintenance_window" "foo" {
|
||||
name = "maintenance-window-%s"
|
||||
schedule = "cron(0 16 ? * TUE *)"
|
||||
duration = 3
|
||||
cutoff = 1
|
||||
}
|
||||
|
||||
resource "aws_ssm_maintenance_window_target" "target" {
|
||||
window_id = "${aws_ssm_maintenance_window.foo.id}"
|
||||
resource_type = "INSTANCE"
|
||||
targets {
|
||||
key = "tag:Name"
|
||||
values = ["acceptance_test"]
|
||||
}
|
||||
}
|
||||
`, rName)
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ssm"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func resourceAwsSsmMaintenanceWindowTask() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceAwsSsmMaintenanceWindowTaskCreate,
|
||||
Read: resourceAwsSsmMaintenanceWindowTaskRead,
|
||||
Delete: resourceAwsSsmMaintenanceWindowTaskDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"window_id": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"max_concurrency": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"max_errors": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"task_type": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"task_arn": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"service_role_arn": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"targets": {
|
||||
Type: schema.TypeList,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"key": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"values": {
|
||||
Type: schema.TypeList,
|
||||
Required: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"priority": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"logging_info": {
|
||||
Type: schema.TypeList,
|
||||
MaxItems: 1,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"s3_bucket_name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"s3_region": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"s3_bucket_prefix": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func expandAwsSsmMaintenanceWindowLoggingInfo(config []interface{}) *ssm.LoggingInfo {
|
||||
|
||||
loggingConfig := config[0].(map[string]interface{})
|
||||
|
||||
loggingInfo := &ssm.LoggingInfo{
|
||||
S3BucketName: aws.String(loggingConfig["s3_bucket_name"].(string)),
|
||||
S3Region: aws.String(loggingConfig["s3_region"].(string)),
|
||||
}
|
||||
|
||||
if s := loggingConfig["s3_bucket_prefix"].(string); s != "" {
|
||||
loggingInfo.S3KeyPrefix = aws.String(s)
|
||||
}
|
||||
|
||||
return loggingInfo
|
||||
}
|
||||
|
||||
func flattenAwsSsmMaintenanceWindowLoggingInfo(loggingInfo *ssm.LoggingInfo) []interface{} {
|
||||
|
||||
result := make(map[string]interface{})
|
||||
result["s3_bucket_name"] = *loggingInfo.S3BucketName
|
||||
result["s3_region"] = *loggingInfo.S3Region
|
||||
|
||||
if loggingInfo.S3KeyPrefix != nil {
|
||||
result["s3_bucket_prefix"] = *loggingInfo.S3KeyPrefix
|
||||
}
|
||||
|
||||
return []interface{}{result}
|
||||
}
|
||||
|
||||
func resourceAwsSsmMaintenanceWindowTaskCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
ssmconn := meta.(*AWSClient).ssmconn
|
||||
|
||||
log.Printf("[INFO] Registering SSM Maintenance Window Task")
|
||||
|
||||
params := &ssm.RegisterTaskWithMaintenanceWindowInput{
|
||||
WindowId: aws.String(d.Get("window_id").(string)),
|
||||
MaxConcurrency: aws.String(d.Get("max_concurrency").(string)),
|
||||
MaxErrors: aws.String(d.Get("max_errors").(string)),
|
||||
TaskType: aws.String(d.Get("task_type").(string)),
|
||||
ServiceRoleArn: aws.String(d.Get("service_role_arn").(string)),
|
||||
TaskArn: aws.String(d.Get("task_arn").(string)),
|
||||
Targets: expandAwsSsmMaintenanceWindowTargets(d),
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("priority"); ok {
|
||||
params.Priority = aws.Int64(int64(v.(int)))
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("logging_info"); ok {
|
||||
params.LoggingInfo = expandAwsSsmMaintenanceWindowLoggingInfo(v.([]interface{}))
|
||||
}
|
||||
|
||||
resp, err := ssmconn.RegisterTaskWithMaintenanceWindow(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.SetId(*resp.WindowTaskId)
|
||||
|
||||
return resourceAwsSsmMaintenanceWindowTaskRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsSsmMaintenanceWindowTaskRead(d *schema.ResourceData, meta interface{}) error {
|
||||
ssmconn := meta.(*AWSClient).ssmconn
|
||||
|
||||
params := &ssm.DescribeMaintenanceWindowTasksInput{
|
||||
WindowId: aws.String(d.Get("window_id").(string)),
|
||||
}
|
||||
|
||||
resp, err := ssmconn.DescribeMaintenanceWindowTasks(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, t := range resp.Tasks {
|
||||
if *t.WindowTaskId == d.Id() {
|
||||
found = true
|
||||
|
||||
d.Set("window_id", t.WindowId)
|
||||
d.Set("max_concurrency", t.MaxConcurrency)
|
||||
d.Set("max_errors", t.MaxErrors)
|
||||
d.Set("task_type", t.Type)
|
||||
d.Set("service_role_arn", t.ServiceRoleArn)
|
||||
d.Set("task_arn", t.TaskArn)
|
||||
d.Set("priority", t.Priority)
|
||||
|
||||
if t.LoggingInfo != nil {
|
||||
if err := d.Set("logging_info", flattenAwsSsmMaintenanceWindowLoggingInfo(t.LoggingInfo)); err != nil {
|
||||
return fmt.Errorf("[DEBUG] Error setting logging_info error: %#v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := d.Set("targets", flattenAwsSsmMaintenanceWindowTargets(t.Targets)); err != nil {
|
||||
return fmt.Errorf("[DEBUG] Error setting targets error: %#v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
log.Printf("[INFO] Maintenance Window Target not found. Removing from state")
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsSsmMaintenanceWindowTaskDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
ssmconn := meta.(*AWSClient).ssmconn
|
||||
|
||||
log.Printf("[INFO] Deregistering SSM Maintenance Window Task: %s", d.Id())
|
||||
|
||||
params := &ssm.DeregisterTaskFromMaintenanceWindowInput{
|
||||
WindowId: aws.String(d.Get("window_id").(string)),
|
||||
WindowTaskId: aws.String(d.Id()),
|
||||
}
|
||||
|
||||
_, err := ssmconn.DeregisterTaskFromMaintenanceWindow(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/service/ssm"
|
||||
"github.com/hashicorp/terraform/helper/acctest"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccAWSSSMMaintenanceWindowTask_basic(t *testing.T) {
|
||||
name := acctest.RandString(10)
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSSSMMaintenanceWindowTaskDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccAWSSSMMaintenanceWindowTaskBasicConfig(name),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSSSMMaintenanceWindowTaskExists("aws_ssm_maintenance_window_task.target"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckAWSSSMMaintenanceWindowTaskExists(n string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No SSM Maintenance Window Task Window ID is set")
|
||||
}
|
||||
|
||||
conn := testAccProvider.Meta().(*AWSClient).ssmconn
|
||||
|
||||
resp, err := conn.DescribeMaintenanceWindowTasks(&ssm.DescribeMaintenanceWindowTasksInput{
|
||||
WindowId: aws.String(rs.Primary.Attributes["window_id"]),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, i := range resp.Tasks {
|
||||
if *i.WindowTaskId == rs.Primary.ID {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("No AWS SSM Maintenance window task found")
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckAWSSSMMaintenanceWindowTaskDestroy(s *terraform.State) error {
|
||||
conn := testAccProvider.Meta().(*AWSClient).ssmconn
|
||||
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "aws_ssm_maintenance_window_target" {
|
||||
continue
|
||||
}
|
||||
|
||||
out, err := conn.DescribeMaintenanceWindowTasks(&ssm.DescribeMaintenanceWindowTasksInput{
|
||||
WindowId: aws.String(rs.Primary.Attributes["window_id"]),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
// Verify the error is what we want
|
||||
if ae, ok := err.(awserr.Error); ok && ae.Code() == "DoesNotExistException" {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if len(out.Tasks) > 0 {
|
||||
return fmt.Errorf("Expected AWS SSM Maintenance Task to be gone, but was still found")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func testAccAWSSSMMaintenanceWindowTaskBasicConfig(rName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_ssm_maintenance_window" "foo" {
|
||||
name = "maintenance-window-%s"
|
||||
schedule = "cron(0 16 ? * TUE *)"
|
||||
duration = 3
|
||||
cutoff = 1
|
||||
}
|
||||
|
||||
resource "aws_ssm_maintenance_window_task" "target" {
|
||||
window_id = "${aws_ssm_maintenance_window.foo.id}"
|
||||
task_type = "RUN_COMMAND"
|
||||
task_arn = "AWS-RunShellScript"
|
||||
priority = 1
|
||||
service_role_arn = "${aws_iam_role.ssm_role.arn}"
|
||||
max_concurrency = "2"
|
||||
max_errors = "1"
|
||||
targets {
|
||||
key = "InstanceIds"
|
||||
values = ["${aws_instance.foo.id}"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_instance" "foo" {
|
||||
ami = "ami-4fccb37f"
|
||||
|
||||
instance_type = "m1.small"
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "ssm_role" {
|
||||
name = "ssm-role-%s"
|
||||
|
||||
assume_role_policy = <<POLICY
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
"Principal": {
|
||||
"Service": "events.amazonaws.com"
|
||||
},
|
||||
"Effect": "Allow",
|
||||
"Sid": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
POLICY
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "bar" {
|
||||
name = "ssm_role_policy_%s"
|
||||
role = "${aws_iam_role.ssm_role.name}"
|
||||
|
||||
policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": {
|
||||
"Effect": "Allow",
|
||||
"Action": "ssm:*",
|
||||
"Resource": "*"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
`, rName, rName, rName)
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ssm"
|
||||
"github.com/hashicorp/terraform/helper/acctest"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccAWSSSMMaintenanceWindow_basic(t *testing.T) {
|
||||
name := acctest.RandString(10)
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSSSMMaintenanceWindowDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccAWSSSMMaintenanceWindowBasicConfig(name),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSSSMMaintenanceWindowExists("aws_ssm_maintenance_window.foo"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_ssm_maintenance_window.foo", "schedule", "cron(0 16 ? * TUE *)"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_ssm_maintenance_window.foo", "duration", "3"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_ssm_maintenance_window.foo", "cutoff", "1"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_ssm_maintenance_window.foo", "name", fmt.Sprintf("maintenance-window-%s", name)),
|
||||
),
|
||||
},
|
||||
{
|
||||
Config: testAccAWSSSMMaintenanceWindowBasicConfigUpdated(name),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSSSMMaintenanceWindowExists("aws_ssm_maintenance_window.foo"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_ssm_maintenance_window.foo", "schedule", "cron(0 16 ? * WED *)"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_ssm_maintenance_window.foo", "duration", "10"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_ssm_maintenance_window.foo", "cutoff", "8"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_ssm_maintenance_window.foo", "name", fmt.Sprintf("updated-maintenance-window-%s", name)),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckAWSSSMMaintenanceWindowExists(n string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No SSM Maintenance Window ID is set")
|
||||
}
|
||||
|
||||
conn := testAccProvider.Meta().(*AWSClient).ssmconn
|
||||
|
||||
resp, err := conn.DescribeMaintenanceWindows(&ssm.DescribeMaintenanceWindowsInput{
|
||||
Filters: []*ssm.MaintenanceWindowFilter{
|
||||
{
|
||||
Key: aws.String("Name"),
|
||||
Values: []*string{aws.String(rs.Primary.Attributes["name"])},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
for _, i := range resp.WindowIdentities {
|
||||
if *i.WindowId == rs.Primary.ID {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return fmt.Errorf("No AWS SSM Maintenance window found")
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckAWSSSMMaintenanceWindowDestroy(s *terraform.State) error {
|
||||
conn := testAccProvider.Meta().(*AWSClient).ssmconn
|
||||
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "aws_ssm_maintenance_window" {
|
||||
continue
|
||||
}
|
||||
|
||||
out, err := conn.DescribeMaintenanceWindows(&ssm.DescribeMaintenanceWindowsInput{
|
||||
Filters: []*ssm.MaintenanceWindowFilter{
|
||||
{
|
||||
Key: aws.String("Name"),
|
||||
Values: []*string{aws.String(rs.Primary.Attributes["name"])},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(out.WindowIdentities) > 0 {
|
||||
return fmt.Errorf("Expected AWS SSM Maintenance Document to be gone, but was still found")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func testAccAWSSSMMaintenanceWindowBasicConfig(rName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_ssm_maintenance_window" "foo" {
|
||||
name = "maintenance-window-%s"
|
||||
schedule = "cron(0 16 ? * TUE *)"
|
||||
duration = 3
|
||||
cutoff = 1
|
||||
}
|
||||
|
||||
`, rName)
|
||||
}
|
||||
|
||||
func testAccAWSSSMMaintenanceWindowBasicConfigUpdated(rName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_ssm_maintenance_window" "foo" {
|
||||
name = "updated-maintenance-window-%s"
|
||||
schedule = "cron(0 16 ? * WED *)"
|
||||
duration = 10
|
||||
cutoff = 8
|
||||
}
|
||||
|
||||
`, rName)
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
layout: "aws"
|
||||
page_title: "AWS: aws_ssm_maintenance_window"
|
||||
sidebar_current: "docs-aws-resource-ssm-maintenance-window"
|
||||
description: |-
|
||||
Provides an SSM Maintenance Window resource
|
||||
---
|
||||
|
||||
# aws_ssm_maintenance_window
|
||||
|
||||
Provides an SSM Maintenance Window resource
|
||||
|
||||
## Example Usage
|
||||
|
||||
```hcl
|
||||
resource "aws_ssm_maintenance_window" "production" {
|
||||
name = "maintenance-window-application"
|
||||
schedule = "cron(0 16 ? * TUE *)"
|
||||
duration = 3
|
||||
cutoff = 1
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `name` - (Required) The name of the maintenance window.
|
||||
* `schedule` - (Required) The schedule of the Maintenance Window in the form of a [cron](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-maintenance-cron.html) or rate expression.
|
||||
* `cutoff` - (Required) The number of hours before the end of the Maintenance Window that Systems Manager stops scheduling new tasks for execution.
|
||||
* `duration` - (Required) The duration of the Maintenance Window in hours.
|
||||
* `allow_unregistered_targets` - (Optional) Whether targets must be registered with the Maintenance Window before tasks can be defined for those targets.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `id` - The ID of the maintenance window.
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
layout: "aws"
|
||||
page_title: "AWS: aws_ssm_maintenance_window_target"
|
||||
sidebar_current: "docs-aws-resource-ssm-maintenance-window-target"
|
||||
description: |-
|
||||
Provides an SSM Maintenance Window Target resource
|
||||
---
|
||||
|
||||
# aws_ssm_maintenance_window_target
|
||||
|
||||
Provides an SSM Maintenance Window Target resource
|
||||
|
||||
## Example Usage
|
||||
|
||||
```hcl
|
||||
resource "aws_ssm_maintenance_window" "window" {
|
||||
name = "maintenance-window-webapp"
|
||||
schedule = "cron(0 16 ? * TUE *)"
|
||||
duration = 3
|
||||
cutoff = 1
|
||||
}
|
||||
|
||||
resource "aws_ssm_maintenance_window_target" "target1" {
|
||||
window_id = "${aws_ssm_maintenance_window.window.id}"
|
||||
resource_type = "INSTANCE"
|
||||
targets {
|
||||
key = "tag:Name"
|
||||
values = ["acceptance_test"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `window_id` - (Required) The Id of the maintenance window to register the target with.
|
||||
* `resource_type` - (Required) The type of target being registered with the Maintenance Window. Possible values `INSTANCE`.
|
||||
* `targets` - (Required) The targets (either instances or tags). Instances are specified using Key=instanceids,Values=instanceid1,instanceid2. Tags are specified using Key=tag name,Values=tag value.
|
||||
* `owner_information` - (Optional) User-provided value that will be included in any CloudWatch events raised while running tasks for these targets in this Maintenance Window.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `id` - The ID of the maintenance window target.
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
layout: "aws"
|
||||
page_title: "AWS: aws_ssm_maintenance_window_task"
|
||||
sidebar_current: "docs-aws-resource-ssm-maintenance-window-task"
|
||||
description: |-
|
||||
Provides an SSM Maintenance Window Task resource
|
||||
---
|
||||
|
||||
# aws_ssm_maintenance_window_task
|
||||
|
||||
Provides an SSM Maintenance Window Task resource
|
||||
|
||||
## Example Usage
|
||||
|
||||
```hcl
|
||||
resource "aws_ssm_maintenance_window" "window" {
|
||||
name = "maintenance-window-%s"
|
||||
schedule = "cron(0 16 ? * TUE *)"
|
||||
duration = 3
|
||||
cutoff = 1
|
||||
}
|
||||
|
||||
resource "aws_ssm_maintenance_window_task" "target" {
|
||||
window_id = "${aws_ssm_maintenance_window.window.id}"
|
||||
task_type = "RUN_COMMAND"
|
||||
task_arn = "AWS-RunShellScript"
|
||||
priority = 1
|
||||
service_role_arn = "arn:aws:iam::187416307283:role/service-role/AWS_Events_Invoke_Run_Command_112316643"
|
||||
max_concurrency = "2"
|
||||
max_errors = "1"
|
||||
targets {
|
||||
key = "InstanceIds"
|
||||
values = ["${aws_instance.instance.id}"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_instance" "instance" {
|
||||
ami = "ami-4fccb37f"
|
||||
|
||||
instance_type = "m1.small"
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `window_id` - (Required) The Id of the maintenance window to register the task with.
|
||||
* `max_concurrency` - (Required) The maximum number of targets this task can be run for in parallel.
|
||||
* `max_errors` - (Required) The maximum number of errors allowed before this task stops being scheduled.
|
||||
* `task_type` - (Required) The type of task being registered. The only allowed value is `RUN_COMMAND`.
|
||||
* `task_arn` - (Required) The ARN of the task to execute.
|
||||
* `service_role_arn` - (Required) The role that should be assumed when executing the task.
|
||||
* `targets` - (Required) The targets (either instances or tags). Instances are specified using Key=instanceids,Values=instanceid1,instanceid2. Tags are specified using Key=tag name,Values=tag value.
|
||||
* `priority` - (Optional) The priority of the task in the Maintenance Window, the lower the number the higher the priority. Tasks in a Maintenance Window are scheduled in priority order with tasks that have the same priority scheduled in parallel.
|
||||
* `logging_info` - (Optional) A structure containing information about an Amazon S3 bucket to write instance-level logs to. Documented below.
|
||||
|
||||
`logging_info` supports the following:
|
||||
|
||||
* `s3_bucket_name` - (Required)
|
||||
* `s3_region` - (Required)
|
||||
* `s3_bucket_prefix` - (Optional)
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `id` - The ID of the maintenance window task.
|
|
@ -1249,6 +1249,18 @@
|
|||
<a href="/docs/providers/aws/r/ssm_document.html">aws_ssm_document</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-aws-resource-ssm-maintenance-window") %>>
|
||||
<a href="/docs/providers/aws/r/ssm_maintenance_window.html">aws_ssm_maintenance_window</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-aws-resource-ssm-maintenance-window-target") %>>
|
||||
<a href="/docs/providers/aws/r/ssm_maintenance_window_target.html">aws_ssm_maintenance_window_target</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-aws-resource-ssm-maintenance-window-task") %>>
|
||||
<a href="/docs/providers/aws/r/ssm_maintenance_window_task.html">aws_ssm_maintenance_window_task</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
|
Loading…
Reference in New Issue