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

Cloud functions #899

Merged
merged 37 commits into from
Jan 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
eedd890
Initial commit
sarunask Nov 21, 2017
5c394fa
Adding google_cloudfunction_function resource
sarunask Dec 14, 2017
93f5856
Merge remote-tracking branch 'upstream/master' into cloud-functions
sarunask Dec 14, 2017
8288741
Some FMT updates
sarunask Dec 14, 2017
c74e219
Working Cloud Function Create/Delete/Get
sarunask Dec 18, 2017
70c6fe9
Merge remote-tracking branch 'upstream/master' into cloud-functions
sarunask Dec 18, 2017
c169968
Fixed tests import
sarunask Dec 18, 2017
b0939d0
Terraform now is able to apply and destroy function
sarunask Dec 21, 2017
6fd1f58
Merge remote-tracking branch 'upstream/master' into cloud-functions
sarunask Dec 21, 2017
28ca0a8
Merge remote-tracking branch 'upstream/master' into cloud-functions
sarunask Dec 23, 2017
127b69c
Fully working Basic test
sarunask Dec 23, 2017
463af45
Added:
sarunask Dec 23, 2017
0c52870
Found better solution for conflicting values
sarunask Dec 24, 2017
e65ab5f
Adding description
sarunask Dec 24, 2017
0180d8d
Adding full basic test
sarunask Dec 24, 2017
3696812
dded Update functionality
sarunask Dec 24, 2017
859ed3b
Made few more optional params
sarunask Dec 24, 2017
94c2e50
Added test for Labels
sarunask Dec 24, 2017
361691d
Added update tests
sarunask Dec 24, 2017
898cfad
Added storage_* members and made function source deploy from storage …
sarunask Dec 25, 2017
5387b18
Adding comments
sarunask Dec 25, 2017
992b7a8
Adding tests for PubSub
sarunask Dec 26, 2017
ea2abdb
Adding tests for Bucket
sarunask Dec 26, 2017
45cace1
Adding Data provider
sarunask Dec 26, 2017
6623728
Fixing bug which allowed to miss error
sarunask Dec 26, 2017
2e31b1d
Amending Operation retrieval
sarunask Dec 26, 2017
02d5847
Merge remote-tracking branch 'upstream/master' into cloud-functions
sarunask Jan 3, 2018
ee5da4a
Fixing vet errors and vendoring cloudfunctions/v1
sarunask Jan 3, 2018
ea9f204
Merge remote-tracking branch 'upstream/master' into cloud-functions
sarunask Jan 6, 2018
172564a
Fixing according to comments
sarunask Jan 6, 2018
3d13310
Merge remote-tracking branch 'upstream/master' into cloud-functions
sarunask Jan 9, 2018
d9a36e8
Fixing according to comments round #2
sarunask Jan 9, 2018
f1e6cec
Fixing tabs to space
sarunask Jan 9, 2018
f466669
Fixing tabs to space and some comments #3
sarunask Jan 10, 2018
ea526b3
Re-done update to include labels in one update with others
sarunask Jan 10, 2018
79db2cf
Adding back default values. In case of such scenario, when user creat…
sarunask Jan 10, 2018
1478794
Fixed MixedCase and more tabs
sarunask Jan 10, 2018
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
70 changes: 70 additions & 0 deletions google/cloudfunctions_operation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package google

import (
"fmt"
"log"
"time"

"github.com/hashicorp/terraform/helper/resource"
"google.golang.org/api/cloudfunctions/v1"
)

type CloudFunctionsOperationWaiter struct {
Service *cloudfunctions.Service
Op *cloudfunctions.Operation
}

func (w *CloudFunctionsOperationWaiter) RefreshFunc() resource.StateRefreshFunc {
return func() (interface{}, string, error) {
op, err := w.Service.Operations.Get(w.Op.Name).Do()

if err != nil {
return nil, "", err
}

status := "PENDING"
if op.Done == true {
status = "DONE"
}

log.Printf("[DEBUG] Got %q when asking for operation %q", status, w.Op.Name)
return op, status, nil
}
}

func (w *CloudFunctionsOperationWaiter) Conf() *resource.StateChangeConf {
return &resource.StateChangeConf{
Pending: []string{"PENDING"},
Target: []string{"DONE"},
Refresh: w.RefreshFunc(),
}
}

func cloudFunctionsOperationWait(client *cloudfunctions.Service,
op *cloudfunctions.Operation, activity string) error {
return cloudFunctionsOperationWaitTime(client, op, activity, 4)
}

func cloudFunctionsOperationWaitTime(client *cloudfunctions.Service, op *cloudfunctions.Operation,
activity string, timeoutMin int) error {
w := &CloudFunctionsOperationWaiter{
Service: client,
Op: op,
}

state := w.Conf()
state.Delay = 10 * time.Second
state.Timeout = time.Duration(timeoutMin) * time.Minute
state.MinTimeout = 2 * time.Second
opRaw, err := state.WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for %s: %s", activity, err)
}

resultOp := opRaw.(*cloudfunctions.Operation)
if resultOp.Error != nil {
return fmt.Errorf(resultOp.Error.Message)
}

return nil
}
9 changes: 9 additions & 0 deletions google/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"golang.org/x/oauth2/jwt"
"google.golang.org/api/bigquery/v2"
"google.golang.org/api/cloudbilling/v1"
"google.golang.org/api/cloudfunctions/v1"
"google.golang.org/api/cloudkms/v1"
"google.golang.org/api/cloudresourcemanager/v1"
resourceManagerV2Beta1 "google.golang.org/api/cloudresourcemanager/v2beta1"
Expand Down Expand Up @@ -64,6 +65,7 @@ type Config struct {
clientIAM *iam.Service
clientServiceMan *servicemanagement.APIService
clientBigQuery *bigquery.Service
clientCloudFunctions *cloudfunctions.Service

bigtableClientFactory *BigtableClientFactory
}
Expand Down Expand Up @@ -244,6 +246,13 @@ func (c *Config) loadAndValidate() error {
}
c.clientBigQuery.UserAgent = userAgent

log.Printf("[INFO] Instantiating Google Cloud CloudFunctions Client...")
c.clientCloudFunctions, err = cloudfunctions.New(client)
if err != nil {
return err
}
c.clientCloudFunctions.UserAgent = userAgent

c.bigtableClientFactory = &BigtableClientFactory{
UserAgent: userAgent,
TokenSource: tokenSource,
Expand Down
45 changes: 45 additions & 0 deletions google/data_source_google_cloudfunctions_function.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package google

import (
"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceGoogleCloudFunctionsFunction() *schema.Resource {
// Generate datasource schema from resource
dsSchema := datasourceSchemaFromResourceSchema(resourceCloudFunctionsFunction().Schema)

// Set 'Required' schema elements
addRequiredFieldsToSchema(dsSchema, "name")

// Set 'Optional' schema elements
addOptionalFieldsToSchema(dsSchema, "project", "region")

return &schema.Resource{
Read: dataSourceGoogleCloudFunctionsFunctionRead,
Schema: dsSchema,
}
}

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

project, err := getProject(d, config)
if err != nil {
return err
}

region, err := getRegion(d, config)
if err != nil {
return err
}

cloudFuncId := &cloudFunctionId{
Project: project,
Region: region,
Name: d.Get("name").(string),
}

d.SetId(cloudFuncId.terraformId())

return resourceCloudFunctionsRead(d, meta)
}
154 changes: 154 additions & 0 deletions google/data_source_google_cloudfunctions_function_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package google

import (
"fmt"
"os"
"testing"

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccDataSourceGoogleCloudFunctionsFunction_basic(t *testing.T) {
t.Parallel()

funcDataNameHttp := "data.google_cloudfunctions_function.function_http"
funcDataNamePubSub := "data.google_cloudfunctions_function.function_pubsub"
funcDataNameBucket := "data.google_cloudfunctions_function.function_bucket"
functionName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
bucketName := fmt.Sprintf("tf-test-bucket-%d", acctest.RandInt())
topicName := fmt.Sprintf("tf-test-sub-%s", acctest.RandString(10))
zipFilePath, err := createZIPArchiveForIndexJs(testHTTPTriggerPath)
if err != nil {
t.Fatal(err.Error())
}
defer os.Remove(zipFilePath) // clean up

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckCloudFunctionsFunctionDestroy,
Steps: []resource.TestStep{
{
Config: testAccDataSourceGoogleCloudFunctionsFunctionConfig(functionName,
bucketName, zipFilePath, topicName),
Check: resource.ComposeTestCheckFunc(
testAccDataSourceGoogleCloudFunctionsFunctionCheck(funcDataNameHttp,
"google_cloudfunctions_function.function_http"),
testAccDataSourceGoogleCloudFunctionsFunctionCheck(funcDataNamePubSub,
"google_cloudfunctions_function.function_pubsub"),
testAccDataSourceGoogleCloudFunctionsFunctionCheck(funcDataNameBucket,
"google_cloudfunctions_function.function_bucket"),
),
},
},
})
}

func testAccDataSourceGoogleCloudFunctionsFunctionCheck(dataSourceName string, resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
ds, ok := s.RootModule().Resources[dataSourceName]
if !ok {
return fmt.Errorf("root module has no resource called %s", dataSourceName)
}

rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("can't find %s in state", resourceName)
}

dsAttr := ds.Primary.Attributes
rsAttr := rs.Primary.Attributes

cloudFuncAttrToCheck := []string{
"name",
"region",
"description",
"available_memory_mb",
"timeout",
"storage_bucket",
"storage_object",
"entry_point",
"trigger_http",
"trigger_bucket",
"trigger_topic",
}

for _, attr := range cloudFuncAttrToCheck {
if dsAttr[attr] != rsAttr[attr] {
return fmt.Errorf(
"%s is %s; want %s",
attr,
dsAttr[attr],
rsAttr[attr],
)
}
}

return nil
}
}

func testAccDataSourceGoogleCloudFunctionsFunctionConfig(functionName string,
bucketName string, zipFilePath string, topicName string) string {
return fmt.Sprintf(`
resource "google_storage_bucket" "bucket" {
name = "%s"
}

resource "google_storage_bucket_object" "archive" {
name = "index.zip"
bucket = "${google_storage_bucket.bucket.name}"
source = "%s"
}

resource "google_cloudfunctions_function" "function_http" {
name = "%s-http"
description = "test function"
available_memory_mb = 128
source_archive_bucket = "${google_storage_bucket.bucket.name}"
source_archive_object = "${google_storage_bucket_object.archive.name}"
trigger_http = true
timeout = 61
entry_point = "helloGET"
}

resource "google_cloudfunctions_function" "function_bucket" {
name = "%s-bucket"
available_memory_mb = 128
source_archive_bucket = "${google_storage_bucket.bucket.name}"
source_archive_object = "${google_storage_bucket_object.archive.name}"
trigger_bucket = "${google_storage_bucket.bucket.name}"
timeout = 61
entry_point = "helloGET"
}

resource "google_pubsub_topic" "sub" {
name = "%s"
}

resource "google_cloudfunctions_function" "function_pubsub" {
name = "%s-pubsub"
available_memory_mb = 128
source_archive_bucket = "${google_storage_bucket.bucket.name}"
source_archive_object = "${google_storage_bucket_object.archive.name}"
trigger_topic = "${google_pubsub_topic.sub.name}"
timeout = 61
entry_point = "helloGET"
}

data "google_cloudfunctions_function" "function_http" {
name = "${google_cloudfunctions_function.function_http.name}"
}

data "google_cloudfunctions_function" "function_bucket" {
name = "${google_cloudfunctions_function.function_bucket.name}"
}

data "google_cloudfunctions_function" "function_pubsub" {
name = "${google_cloudfunctions_function.function_pubsub.name}"
}
`, bucketName, zipFilePath, functionName, functionName,
topicName, functionName)
}
2 changes: 2 additions & 0 deletions google/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ func Provider() terraform.ResourceProvider {
"google_billing_account": dataSourceGoogleBillingAccount(),
"google_dns_managed_zone": dataSourceDnsManagedZone(),
"google_client_config": dataSourceGoogleClientConfig(),
"google_cloudfunctions_function": dataSourceGoogleCloudFunctionsFunction(),
"google_compute_address": dataSourceGoogleComputeAddress(),
"google_compute_image": dataSourceGoogleComputeImage(),
"google_compute_global_address": dataSourceGoogleComputeGlobalAddress(),
Expand All @@ -86,6 +87,7 @@ func Provider() terraform.ResourceProvider {
"google_bigquery_table": resourceBigQueryTable(),
"google_bigtable_instance": resourceBigtableInstance(),
"google_bigtable_table": resourceBigtableTable(),
"google_cloudfunctions_function": resourceCloudFunctionsFunction(),
"google_compute_autoscaler": resourceComputeAutoscaler(),
"google_compute_address": resourceComputeAddress(),
"google_compute_backend_bucket": resourceComputeBackendBucket(),
Expand Down
Loading