Skip to content
This repository was archived by the owner on Jun 27, 2021. It is now read-only.
Open
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
17 changes: 17 additions & 0 deletions examples/alias/basic_example.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
resource "gsuite_user" "test" {
name = {
family_name = "TestAcc_replaceWithUuid"
given_name = "Test"
}

primary_email = "[email protected]"

lifecycle {
ignore = [aliases]
}
}

resource "gsuite_user_alias" "test" {
user_id = gsuite_user.test.primary_email
alias = "[email protected]"
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.15

require (
cloud.google.com/go v0.79.0
github.com/cenkalti/backoff/v4 v4.1.1
github.com/golang/protobuf v1.5.2 // indirect
github.com/hashicorp/terraform-plugin-sdk v1.13.0
github.com/pkg/errors v0.9.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1U
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
Expand Down
1 change: 1 addition & 0 deletions gsuite/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func Provider() *schema.Provider {
"gsuite_group_members": resourceGroupMembers(),
"gsuite_group_settings": resourceGroupSettings(),
"gsuite_user": resourceUser(),
"gsuite_user_alias": resourceUserAlias(),
"gsuite_user_attributes": resourceUserAttributes(),
"gsuite_user_schema": resourceUserSchema(),
},
Expand Down
153 changes: 153 additions & 0 deletions gsuite/resource_user_alias.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package gsuite

import (
"fmt"
"log"
"reflect"
"strings"
"time"

"github.com/cenkalti/backoff/v4"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
admin "google.golang.org/api/admin/directory/v1"
)

func resourceUserAlias() *schema.Resource {
return &schema.Resource{
Create: resourceUserAliasCreate,
Read: resourceUserAliasRead,
Update: nil,
Delete: resourceUserAliasDelete,
Importer: &schema.ResourceImporter{
State: resourceUserAliasImport,
},
Schema: map[string]*schema.Schema{
"user_id": {
Type: schema.TypeString,
Description: "ID (userKey) of the user the alias should be applied to.",
Required: true,
ForceNew: true,
},
"alias": {
Type: schema.TypeString,
Description: "Email alias which should be applied to the user.",
Required: true,
ForceNew: true,
ValidateFunc: validateEmail,
},
},
}
}

func resourceUserAliasCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

userId := d.Get("user_id").(string)
setAlias := d.Get("alias").(string)

alias := &admin.Alias{
Alias: setAlias,
}
resp, err := config.directory.Users.Aliases.Insert(userId, alias).Do()
if err != nil {
return fmt.Errorf("[ERROR] failed to add alias for user (%s): %v", userId, err)
}

bOff := backoff.NewExponentialBackOff()
bOff.MaxElapsedTime = time.Duration(config.TimeoutMinutes) * time.Minute
bOff.InitialInterval = time.Second

err = backoff.Retry(func() error {
resp, err := config.directory.Users.Aliases.List(userId).Do()
if err != nil {
return backoff.Permanent(fmt.Errorf("[ERROR] could not retrieve aliases for user (%s): %v", userId, err))
}

_, ok := doesAliasExist(resp, setAlias)
if ok {
return nil
}
return fmt.Errorf(fmt.Sprintf("[WARN] no matching alias (%s) found for user (%s).", setAlias, userId))

}, bOff)

d.SetId(fmt.Sprintf("%s/%s", resp.PrimaryEmail, resp.Alias))
return resourceUserAliasRead(d, meta)
}

func resourceUserAliasRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

userId := d.Get("user_id").(string)
expectedAlias := d.Get("alias").(string)

resp, err := config.directory.Users.Aliases.List(userId).Do()
if err != nil {
return fmt.Errorf("[ERROR] could not retrieve aliases for user (%s): %v", userId, err)
}

alias, ok := doesAliasExist(resp, expectedAlias)
if !ok {
log.Println(fmt.Sprintf("[WARN] no matching alias (%s) found for user (%s).", expectedAlias, userId))
d.SetId("")
return nil
}
d.SetId(fmt.Sprintf("%s/%s", userId, alias))
d.Set("user_id", userId)
d.Set("alias", alias)
return nil
}

func resourceUserAliasDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

userId := d.Get("user_id").(string)
alias := d.Get("alias").(string)

err := config.directory.Users.Aliases.Delete(userId, alias).Do()
if err != nil {
return fmt.Errorf("[ERROR] unable to remove alias (%s) from user (%s): %v", alias, userId, err)
}

d.SetId("")
return nil
}

func resourceUserAliasImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)

userId := strings.Split(d.Id(), "/")[0]
expectedAlias := strings.Split(d.Id(), "/")[1]

resp, err := config.directory.Users.Aliases.List(userId).Do()
if err != nil {
return nil, fmt.Errorf("[ERROR] could not retrieve aliases for user (%s): %v", userId, err)
}

alias, ok := doesAliasExist(resp, expectedAlias)
if !ok {
return nil, fmt.Errorf("[ERROR] no matching alias (%s) found for user (%s).", expectedAlias, userId)
}
d.SetId(fmt.Sprintf("%s/%s", userId, alias))
d.Set("user_id", userId)
d.Set("alias", alias)

return []*schema.ResourceData{d}, nil
}

func doesAliasExist(aliasesResp *admin.Aliases, expectedAlias string) (string, bool) {
for _, aliasInt := range aliasesResp.Aliases {
alias, ok := aliasInt.(map[string]interface{})
if ok {
value := alias["alias"].(string)
if expectedAlias == alias["alias"].(string) {
return value, true
}
}
if !ok {
log.Println(fmt.Sprintf("[ERROR] alias format in response did not match sdk struct, this indicates a probelm with provider or sdk handling: %v", reflect.TypeOf(aliasInt)))
return "", false
}
}
return "", false
}
39 changes: 39 additions & 0 deletions website/docs/r/user_alias.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
layout: "gsuite"
page_title: "G Suite: gsuite_alias"
sidebar_current: "docs-gsuite-resource-user-alias"
description: |-
Managing a G Suite User Alias.
---

# gsuite_user_alias

Provides a resource for creating and managing an email alias for a GSuite user account.

## Example Usage

```hcl
resource "gsuite_user_alias" "test" {
user_id = "[email protected]"
alias = "[email protected]"
}
```

## Argument Reference

* `user_id` (Required) Primary email (userKey) of the user who will have the alias applied to them.
* `alias` (Required) Email alias to be applied to the user.


## Attribute Reference

N/A apart from the included arguments

## Import

An alias can be imported by passing the ID format of "{user_id}/{alias}"

For example:
```
terraform import gsuite_user_alias.test "[email protected]/[email protected]"
```