Skip to content

Commit

Permalink
Merge pull request #3 from zambien/master
Browse files Browse the repository at this point in the history
Merge latest master into forked repo
  • Loading branch information
zkauker authored Nov 15, 2019
2 parents e632872 + feb5e02 commit e106d18
Show file tree
Hide file tree
Showing 11 changed files with 762 additions and 23 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,30 @@ resource "apigee_company_app" "helloworld_company_app" {
callback_url = "https://www.google.com"
}
# Create the shared flow bundle pretty much the same way you create the proxy bundle.
data "archive_file" "sharedflow_bundle" {
type = "zip"
source_dir = "${path.module}/sharedflow_files"
output_path = "${path.module}/sharedflow_files_bundle/sharedflow.zip"
}
# The Shared Flow
resource "apigee_shared_flow" "helloworld_shared_flow" {
name = "helloworld-sharedflow-terraformed" # The shared flow's name.
bundle = "${data.archive_file.sharedflow_bundle.output_path}" # Apigee APIs require a zip bundle to import a shared flow.
bundle_sha = "${data.archive_file.sharedflow_bundle.output_sha}" # The SHA is used to detect changes for plan/apply.
}
# A Shared Flow deployment
resource "apigee_shared_flow_deployment" "helloworld_shared_flow_deployment" {
shared_flow_name = "${apigee_shared_flow.helloworld_shared_flow.name}"
org = "${var.org}"
env = "${var.env}"
# NOTE: revision = "latest"
# will deploy the latest revision of the shared flow
revision = "${apigee_shared_flow.helloworld_shared_flow.revision}"
}
```

## Contributions
Expand Down
12 changes: 10 additions & 2 deletions apigee/helpers.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package apigee

import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/zambien/go-apigee-edge"
"reflect"
"sort"

"github.com/hashicorp/terraform/helper/schema"
"github.com/zambien/go-apigee-edge"
)

func flattenStringList(list []string) []interface{} {
Expand Down Expand Up @@ -75,3 +76,10 @@ func arraySortedEqual(a, b []string) bool {

return reflect.DeepEqual(a_copy, b_copy)
}

func updateResourceOnSortedArrayChange(d *schema.ResourceData, key string, newValues []string) {
currentValues := getStringList(key, d)
if currentValues != nil && !arraySortedEqual(currentValues, newValues) {
d.Set(key, newValues)
}
}
18 changes: 10 additions & 8 deletions apigee/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,16 @@ func Provider() terraform.ResourceProvider {
},

ResourcesMap: map[string]*schema.Resource{
"apigee_api_proxy": resourceApiProxy(),
"apigee_api_proxy_deployment": resourceApiProxyDeployment(),
"apigee_company": resourceCompany(),
"apigee_company_app": resourceCompanyApp(),
"apigee_developer": resourceDeveloper(),
"apigee_developer_app": resourceDeveloperApp(),
"apigee_product": resourceProduct(),
"apigee_target_server": resourceTargetServer(),
"apigee_api_proxy": resourceApiProxy(),
"apigee_api_proxy_deployment": resourceApiProxyDeployment(),
"apigee_company": resourceCompany(),
"apigee_company_app": resourceCompanyApp(),
"apigee_developer": resourceDeveloper(),
"apigee_developer_app": resourceDeveloperApp(),
"apigee_product": resourceProduct(),
"apigee_target_server": resourceTargetServer(),
"apigee_shared_flow": resourceSharedFlow(),
"apigee_shared_flow_deployment": resourceSharedFlowDeployment(),
},

ConfigureFunc: configureProvider,
Expand Down
14 changes: 5 additions & 9 deletions apigee/resource_product.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,6 @@ func resourceProductRead(d *schema.ResourceData, meta interface{}) error {
}
}

apiResources := flattenStringList(ProductData.ApiResources)
proxies := flattenStringList(ProductData.Proxies)
scopes := flattenStringList(ProductData.Scopes)
environments := flattenStringList(ProductData.Environments)

d.Set("name", ProductData.Name)

if ProductData.DisplayName == "" {
Expand All @@ -174,13 +169,14 @@ func resourceProductRead(d *schema.ResourceData, meta interface{}) error {
d.Set("description", ProductData.Description)
d.Set("approval_type", ProductData.ApprovalType)
d.Set("attributes", ProductData.Attributes)
d.Set("apiResource", apiResources)
d.Set("proxies", proxies)
d.Set("quota", ProductData.Quota)
d.Set("quota_interval", ProductData.QuotaInterval)
d.Set("quota_time_unit", ProductData.QuotaTimeUnit)
d.Set("environments", environments)
d.Set("scopes", scopes)

updateResourceOnSortedArrayChange(d, "apiResource", ProductData.ApiResources)
updateResourceOnSortedArrayChange(d, "proxies", ProductData.Proxies)
updateResourceOnSortedArrayChange(d, "environments", ProductData.Environments)
updateResourceOnSortedArrayChange(d, "scopes", ProductData.Scopes)

return nil
}
Expand Down
21 changes: 17 additions & 4 deletions apigee/resource_product_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package apigee

import (
"fmt"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/zambien/go-apigee-edge"
"log"
"strings"
"testing"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/zambien/go-apigee-edge"
)

func TestAccProduct_Updated(t *testing.T) {
Expand Down Expand Up @@ -108,14 +109,26 @@ resource "apigee_api_proxy" "tf_helloworld" {
bundle_sha = "${filebase64sha256("test-fixtures/helloworld_proxy.zip")}"
}
resource "apigee_api_proxy" "tf_helloworld_2" {
name = "tf_helloworld_2"
bundle = "test-fixtures/helloworld_proxy.zip"
bundle_sha = "${filebase64sha256("test-fixtures/helloworld_proxy.zip")}"
}
resource "apigee_api_proxy" "tf_helloworld_3" {
name = "tf_helloworld_3"
bundle = "test-fixtures/helloworld_proxy.zip"
bundle_sha = "${filebase64sha256("test-fixtures/helloworld_proxy.zip")}"
}
resource "apigee_product" "foo_product" {
name = "foo_product_updated"
display_name = "foo_product_updated_different"
description = "no one ever fills this out"
approval_type = "auto"
api_resources = ["/**"]
proxies = ["${apigee_api_proxy.tf_helloworld.name}"]
proxies = ["${apigee_api_proxy.tf_helloworld.name}", "${apigee_api_proxy.tf_helloworld_2.name}", "${apigee_api_proxy.tf_helloworld_3.name}"]
quota = "1000"
quota_interval = "2"
Expand Down
169 changes: 169 additions & 0 deletions apigee/resource_shared_flow.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package apigee

import (
"strings"

"fmt"
"log"
"strconv"
"time"

"github.com/gofrs/uuid"
"github.com/hashicorp/terraform/helper/schema"
"github.com/zambien/go-apigee-edge"
)

func resourceSharedFlow() *schema.Resource {
return &schema.Resource{
Create: resourceSharedFlowCreate,
Read: resourceSharedFlowRead,
Update: resourceSharedFlowUpdate,
Delete: resourceSharedFlowDelete,
Importer: &schema.ResourceImporter{
State: resourceSharedFlowImport,
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"bundle": {
Type: schema.TypeString,
Required: true,
},
"bundle_sha": {
Type: schema.TypeString,
Required: true,
},
//revision_sha is used as a workaround for: https://github.com/hashicorp/terraform/issues/15857
"revision_sha": {
Type: schema.TypeString,
Computed: true,
},
"revision": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func resourceSharedFlowCreate(d *schema.ResourceData, meta interface{}) error {
log.Print("[DEBUG] resourceSharedFlowCreate START")

client := meta.(*apigee.EdgeClient)

u1, _ := uuid.NewV4()

sharedFlowRev, _, err := client.SharedFlows.Import(d.Get("name").(string), d.Get("bundle").(string))

if err != nil {
log.Printf("[ERROR] resourceSharedFlowCreate error importing shared_flow: %s", err.Error())
return fmt.Errorf("[ERROR] resourceSharedFlowCreate error importing shared_flow: %s", err.Error())
}

d.SetId(u1.String())
d.Set("name", d.Get("name").(string))
d.Set("revision", sharedFlowRev.Revision.String())
d.Set("revision_sha", d.Get("bundle_sha").(string))

return resourceSharedFlowRead(d, meta)
}

func resourceSharedFlowImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
log.Print("[DEBUG] resourceSharedFlowImport START")

client := meta.(*apigee.EdgeClient)
sharedFlow, _, err := client.SharedFlows.Get(d.Id())
if err != nil {
return []*schema.ResourceData{}, fmt.Errorf("[DEBUG] resourceSharedFlowImport. Error getting deployment shared flow: %v", err)
}
latestRev := strconv.Itoa(len(sharedFlow.Revisions))
d.Set("revision", latestRev)
d.Set("name", d.Id())
return []*schema.ResourceData{d}, nil
}

func resourceSharedFlowRead(d *schema.ResourceData, meta interface{}) error {
log.Print("[DEBUG] resourceSharedFlowRead START")

client := meta.(*apigee.EdgeClient)

u, _, err := client.SharedFlows.Get(d.Get("name").(string))
if err != nil {
log.Printf("[ERROR] resourceSharedFlowRead error reading shared flows: %s", err.Error())
if strings.Contains(err.Error(), "404 ") {
log.Printf("[DEBUG] resourceSharedFlowRead 404 encountered. Removing state for shared flow: %#v", d.Get("name").(string))
d.SetId("")
return nil
} else {
return fmt.Errorf("[ERROR] resourceSharedFlowRead error reading shared flows: %s", err.Error())
}
}

latestRev := strconv.Itoa(len(u.Revisions))

log.Printf("[DEBUG] resourceSharedFlowRead. revision_sha before: %#v", d.Get("revision_sha").(string))
d.Set("revision_sha", d.Get("bundle_sha").(string))
log.Printf("[DEBUG] resourceSharedFlowRead. revision_sha after: %#v", d.Get("revision_sha").(string))
d.Set("revision", latestRev)
d.Set("name", u.Name)

return nil
}

func resourceSharedFlowUpdate(d *schema.ResourceData, meta interface{}) error {

log.Print("[DEBUG] resourceSharedFlowUpdate START")

client := meta.(*apigee.EdgeClient)

if d.HasChange("name") {
log.Printf("[INFO] resourceSharedFlowUpdate name changed to: %#v\n", d.Get("name"))
}

if d.HasChange("bundle_sha") {
log.Printf("[INFO] resourceSharedFlowUpdate bundle_sha changed to: %#v\n", d.Get("bundle_sha"))
}

sharedFlowRev, _, err := client.SharedFlows.Import(d.Get("name").(string), d.Get("bundle").(string))
if err != nil {
log.Printf("[ERROR] resourceSharedFlowUpdate error importing shared flow: %s", err.Error())
return fmt.Errorf("[ERROR] resourceSharedFlowUpdate error importing shared flow: %s", err.Error())
}

d.Set("revision", sharedFlowRev.Revision.String())
d.Set("revision_sha", d.Get("bundle_sha").(string))

return resourceSharedFlowRead(d, meta)
}

func resourceSharedFlowDelete(d *schema.ResourceData, meta interface{}) error {

log.Print("[DEBUG] resourceSharedFlowDelete START")

client := meta.(*apigee.EdgeClient)

//We have to handle retries in a special way here since this is a DELETE. Note this used to work fine without retries.
deleted := false
tries := 0
for !deleted && tries < 3 {
_, _, err := client.SharedFlows.Delete(d.Get("name").(string))
if err != nil {
//This is a race condition with Apigee APIs. Wait and try again.
if strings.Contains(err.Error(), "Undeploy the shared flow and try again") {
log.Printf("[ERROR] resourceSharedFlowDelete shared flow still exists. We will wait and try again.")
time.Sleep(5 * time.Second)
} else {
log.Printf("[ERROR] resourceSharedFlowDelete error deleting shared flow: %s", err.Error())
return fmt.Errorf("[ERROR] resourceSharedFlowDelete error deleting api_proxshared flowy: %s", err.Error())
}
}
deleted = true
tries += tries
}

return nil
}
Loading

0 comments on commit e106d18

Please sign in to comment.