Skip to content

Commit 859171e

Browse files
modular-magiciannat-henderson
authored andcommitted
add souce repo support to cloud functions (#2650)
1 parent 01bdce9 commit 859171e

File tree

3 files changed

+122
-9
lines changed

3 files changed

+122
-9
lines changed

google/resource_cloudfunctions_function.go

+63-5
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,31 @@ func resourceCloudFunctionsFunction() *schema.Resource {
123123

124124
"source_archive_bucket": {
125125
Type: schema.TypeString,
126-
Required: true,
126+
Optional: true,
127127
},
128128

129129
"source_archive_object": {
130130
Type: schema.TypeString,
131-
Required: true,
131+
Optional: true,
132+
},
133+
134+
"source_repository": {
135+
Type: schema.TypeList,
136+
Optional: true,
137+
MaxItems: 1,
138+
ConflictsWith: []string{"source_archive_bucket", "source_archive_object"},
139+
Elem: &schema.Resource{
140+
Schema: map[string]*schema.Schema{
141+
"url": {
142+
Type: schema.TypeString,
143+
Required: true,
144+
},
145+
"deployed_url": {
146+
Type: schema.TypeString,
147+
Computed: true,
148+
},
149+
},
150+
},
132151
},
133152

134153
"description": {
@@ -302,9 +321,17 @@ func resourceCloudFunctionsCreate(d *schema.ResourceData, meta interface{}) erro
302321
ForceSendFields: []string{},
303322
}
304323

305-
sourceArchiveBucket := d.Get("source_archive_bucket").(string)
306-
sourceArchiveObj := d.Get("source_archive_object").(string)
307-
function.SourceArchiveUrl = fmt.Sprintf("gs://%v/%v", sourceArchiveBucket, sourceArchiveObj)
324+
sourceRepos := d.Get("source_repository").([]interface{})
325+
if len(sourceRepos) > 0 {
326+
function.SourceRepository = expandSourceRepository(sourceRepos)
327+
} else {
328+
sourceArchiveBucket := d.Get("source_archive_bucket").(string)
329+
sourceArchiveObj := d.Get("source_archive_object").(string)
330+
if sourceArchiveBucket == "" || sourceArchiveObj == "" {
331+
return fmt.Errorf("either source_repository or both of source_archive_bucket+source_archive_object must be set")
332+
}
333+
function.SourceArchiveUrl = fmt.Sprintf("gs://%v/%v", sourceArchiveBucket, sourceArchiveObj)
334+
}
308335

309336
if v, ok := d.GetOk("available_memory_mb"); ok {
310337
availableMemoryMb := v.(int)
@@ -396,6 +423,7 @@ func resourceCloudFunctionsRead(d *schema.ResourceData, meta interface{}) error
396423
d.Set("source_archive_bucket", bucket)
397424
d.Set("source_archive_object", object)
398425
}
426+
d.Set("source_repository", flattenSourceRepository(function.SourceRepository))
399427

400428
if function.HttpsTrigger != nil {
401429
d.Set("trigger_http", true)
@@ -444,6 +472,11 @@ func resourceCloudFunctionsUpdate(d *schema.ResourceData, meta interface{}) erro
444472
updateMaskArr = append(updateMaskArr, "sourceArchiveUrl")
445473
}
446474

475+
if d.HasChange("source_repository") {
476+
function.SourceRepository = expandSourceRepository(d.Get("source_repository").([]interface{}))
477+
updateMaskArr = append(updateMaskArr, "sourceRepository")
478+
}
479+
447480
if d.HasChange("description") {
448481
function.Description = d.Get("description").(string)
449482
updateMaskArr = append(updateMaskArr, "description")
@@ -608,3 +641,28 @@ func flattenFailurePolicy(failurePolicy *cloudfunctions.FailurePolicy) []map[str
608641

609642
return result
610643
}
644+
645+
func expandSourceRepository(configured []interface{}) *cloudfunctions.SourceRepository {
646+
if len(configured) == 0 || configured[0] == nil {
647+
return &cloudfunctions.SourceRepository{}
648+
}
649+
650+
data := configured[0].(map[string]interface{})
651+
return &cloudfunctions.SourceRepository{
652+
Url: data["url"].(string),
653+
}
654+
}
655+
656+
func flattenSourceRepository(sourceRepo *cloudfunctions.SourceRepository) []map[string]interface{} {
657+
result := make([]map[string]interface{}, 0, 1)
658+
if sourceRepo == nil {
659+
return nil
660+
}
661+
662+
result = append(result, map[string]interface{}{
663+
"url": sourceRepo.Url,
664+
"deployed_url": sourceRepo.DeployedUrl,
665+
})
666+
667+
return result
668+
}

google/resource_cloudfunctions_function_test.go

+42
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,29 @@ func TestAccCloudFunctionsFunction_firestore(t *testing.T) {
234234
})
235235
}
236236

237+
func TestAccCloudFunctionsFunction_sourceRepo(t *testing.T) {
238+
t.Parallel()
239+
240+
funcResourceName := "google_cloudfunctions_function.function"
241+
functionName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
242+
243+
resource.Test(t, resource.TestCase{
244+
PreCheck: func() { testAccPreCheck(t) },
245+
Providers: testAccProviders,
246+
CheckDestroy: testAccCheckCloudFunctionsFunctionDestroy,
247+
Steps: []resource.TestStep{
248+
{
249+
Config: testAccCloudFunctionsFunction_sourceRepo(functionName),
250+
},
251+
{
252+
ResourceName: funcResourceName,
253+
ImportState: true,
254+
ImportStateVerify: true,
255+
},
256+
},
257+
})
258+
}
259+
237260
func testAccCheckCloudFunctionsFunctionDestroy(s *terraform.State) error {
238261
config := testAccProvider.Meta().(*Config)
239262

@@ -564,3 +587,22 @@ resource "google_cloudfunctions_function" "function" {
564587
}
565588
}`, bucketName, zipFilePath, functionName)
566589
}
590+
591+
func testAccCloudFunctionsFunction_sourceRepo(functionName string) string {
592+
return fmt.Sprintf(`
593+
resource "google_cloudfunctions_function" "function" {
594+
name = "%s"
595+
596+
source_repository {
597+
// There isn't yet an API that'll allow us to create a source repository and
598+
// put code in it, so we created this repository outside the test to be used
599+
// here. If this test is run outside of CI, it may fail because of permissions
600+
// errors.
601+
url = "https://source.developers.google.com/projects/hc-terraform-testing/repos/cloudfunctions-test-do-not-delete/moveable-aliases/master/paths/"
602+
}
603+
604+
trigger_http = true
605+
entry_point = "helloGET"
606+
}
607+
`, functionName)
608+
}

website/docs/r/cloudfunctions_function.html.markdown

+17-4
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,6 @@ The following arguments are supported:
5050

5151
* `name` - (Required) A user-defined name of the function. Function names must be unique globally.
5252

53-
* `source_archive_bucket` - (Required) The GCS bucket containing the zip archive which contains the function.
54-
55-
* `source_archive_object` - (Required) The source archive object (file) in archive bucket.
56-
5753
- - -
5854

5955
* `description` - (Optional) Description of the function.
@@ -74,6 +70,13 @@ The following arguments are supported:
7470

7571
* `environment_variables` - (Optional) A set of key/value environment variable pairs to assign to the function.
7672

73+
* `source_archive_bucket` - (Optional) The GCS bucket containing the zip archive which contains the function.
74+
75+
* `source_archive_object` - (Optional) The source archive object (file) in archive bucket.
76+
77+
* `source_repository` - (Optional) Represents parameters related to source repository where a function is hosted.
78+
Cannot be set alongside `source_archive_bucket` or `source_archive_object`. Structure is documented below.
79+
7780
The `event_trigger` block supports:
7881

7982
* `event_type` - (Required) The type of event to observe. For example: `"google.storage.object.finalize"`.
@@ -90,13 +93,23 @@ The `failure_policy` block supports:
9093

9194
* `retry` - (Required) Whether the function should be retried on failure. Defaults to `false`.
9295

96+
The `source_reposoitory` block supports:
97+
98+
* `url` - (Required) The URL pointing to the hosted repository where the function is defined. There are supported Cloud Source Repository URLs in the following formats:
99+
100+
* To refer to a specific commit: `https://source.developers.google.com/projects/*/repos/*/revisions/*/paths/*`
101+
* To refer to a moveable alias (branch): `https://source.developers.google.com/projects/*/repos/*/moveable-aliases/*/paths/*`. To refer to HEAD, use the `master` moveable alias.
102+
* To refer to a specific fixed alias (tag): `https://source.developers.google.com/projects/*/repos/*/fixed-aliases/*/paths/*`
103+
93104
## Attributes Reference
94105

95106
In addition to the arguments listed above, the following computed attributes are
96107
exported:
97108

98109
* `https_trigger_url` - URL which triggers function execution. Returned only if `trigger_http` is used.
99110

111+
* `source_reposoitory.0.deployed_url` - The URL pointing to the hosted repository where the function was defined at the time of deployment.
112+
100113
* `project` - Project of the function. If it is not provided, the provider project is used.
101114

102115
* `region` - Region of function. Currently can be only "us-central1". If it is not provided, the provider region is used.

0 commit comments

Comments
 (0)