Skip to content

Commit c74ca01

Browse files
Update certificate manager certificate to deal with locations (#7825) (#14432)
Signed-off-by: Modular Magician <[email protected]>
1 parent 697846e commit c74ca01

6 files changed

+394
-20
lines changed

.changelog/7825.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
certificatemanager: added `location` field to `certificatemanager` certificate resource
3+
```

google/resource_certificate_manager_certificate.go

+235-9
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package google
1616

1717
import (
18+
"context"
1819
"fmt"
1920
"log"
2021
"reflect"
@@ -49,6 +50,15 @@ func ResourceCertificateManagerCertificate() *schema.Resource {
4950
Delete: schema.DefaultTimeout(20 * time.Minute),
5051
},
5152

53+
SchemaVersion: 1,
54+
StateUpgraders: []schema.StateUpgrader{
55+
{
56+
Type: resourceCertificateManagerCertificateResourceV0().CoreConfigSchema().ImpliedType(),
57+
Upgrade: ResourceCertificateManagerCertificateUpgradeV0,
58+
Version: 0,
59+
},
60+
},
61+
5262
Schema: map[string]*schema.Schema{
5363
"name": {
5464
Type: schema.TypeString,
@@ -69,6 +79,12 @@ and all following characters must be a dash, underscore, letter or digit.`,
6979
Description: `Set of label tags associated with the Certificate resource.`,
7080
Elem: &schema.Schema{Type: schema.TypeString},
7181
},
82+
"location": {
83+
Type: schema.TypeString,
84+
Optional: true,
85+
Description: `The Certificate Manager location. If not specified, "global" is used.`,
86+
Default: "global",
87+
},
7288
"managed": {
7389
Type: schema.TypeList,
7490
Optional: true,
@@ -273,7 +289,7 @@ func resourceCertificateManagerCertificateCreate(d *schema.ResourceData, meta in
273289
obj["managed"] = managedProp
274290
}
275291

276-
url, err := ReplaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificates?certificateId={{name}}")
292+
url, err := ReplaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/{{location}}/certificates?certificateId={{name}}")
277293
if err != nil {
278294
return err
279295
}
@@ -298,7 +314,7 @@ func resourceCertificateManagerCertificateCreate(d *schema.ResourceData, meta in
298314
}
299315

300316
// Store the ID now
301-
id, err := ReplaceVars(d, config, "projects/{{project}}/locations/global/certificates/{{name}}")
317+
id, err := ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/certificates/{{name}}")
302318
if err != nil {
303319
return fmt.Errorf("Error constructing id: %s", err)
304320
}
@@ -326,7 +342,7 @@ func resourceCertificateManagerCertificateRead(d *schema.ResourceData, meta inte
326342
return err
327343
}
328344

329-
url, err := ReplaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificates/{{name}}")
345+
url, err := ReplaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/{{location}}/certificates/{{name}}")
330346
if err != nil {
331347
return err
332348
}
@@ -398,7 +414,7 @@ func resourceCertificateManagerCertificateUpdate(d *schema.ResourceData, meta in
398414
obj["labels"] = labelsProp
399415
}
400416

401-
url, err := ReplaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificates/{{name}}")
417+
url, err := ReplaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/{{location}}/certificates/{{name}}")
402418
if err != nil {
403419
return err
404420
}
@@ -459,7 +475,7 @@ func resourceCertificateManagerCertificateDelete(d *schema.ResourceData, meta in
459475
}
460476
billingProject = project
461477

462-
url, err := ReplaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificates/{{name}}")
478+
url, err := ReplaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/{{location}}/certificates/{{name}}")
463479
if err != nil {
464480
return err
465481
}
@@ -492,15 +508,15 @@ func resourceCertificateManagerCertificateDelete(d *schema.ResourceData, meta in
492508
func resourceCertificateManagerCertificateImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
493509
config := meta.(*transport_tpg.Config)
494510
if err := ParseImportId([]string{
495-
"projects/(?P<project>[^/]+)/locations/global/certificates/(?P<name>[^/]+)",
496-
"(?P<project>[^/]+)/(?P<name>[^/]+)",
497-
"(?P<name>[^/]+)",
511+
"projects/(?P<project>[^/]+)/locations/(?P<location>[^/]+)/certificates/(?P<name>[^/]+)",
512+
"(?P<project>[^/]+)/(?P<location>[^/]+)/(?P<name>[^/]+)",
513+
"(?P<location>[^/]+)/(?P<name>[^/]+)",
498514
}, d, config); err != nil {
499515
return nil, err
500516
}
501517

502518
// Replace import id for the resource id
503-
id, err := ReplaceVars(d, config, "projects/{{project}}/locations/global/certificates/{{name}}")
519+
id, err := ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/certificates/{{name}}")
504520
if err != nil {
505521
return nil, fmt.Errorf("Error constructing id: %s", err)
506522
}
@@ -840,3 +856,213 @@ func expandCertificateManagerCertificateManagedAuthorizationAttemptInfoFailureRe
840856
func expandCertificateManagerCertificateManagedAuthorizationAttemptInfoDetails(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
841857
return v, nil
842858
}
859+
860+
func ResourceCertificateManagerCertificateUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
861+
log.Printf("[DEBUG] Attributes before migration: %#v", rawState)
862+
// Version 0 didn't support location. Default it to global.
863+
rawState["location"] = "global"
864+
log.Printf("[DEBUG] Attributes after migration: %#v", rawState)
865+
return rawState, nil
866+
}
867+
868+
func resourceCertificateManagerCertificateResourceV0() *schema.Resource {
869+
return &schema.Resource{
870+
Create: resourceCertificateManagerCertificateCreate,
871+
Read: resourceCertificateManagerCertificateRead,
872+
Update: resourceCertificateManagerCertificateUpdate,
873+
Delete: resourceCertificateManagerCertificateDelete,
874+
875+
Importer: &schema.ResourceImporter{
876+
State: resourceCertificateManagerCertificateImport,
877+
},
878+
879+
Timeouts: &schema.ResourceTimeout{
880+
Create: schema.DefaultTimeout(20 * time.Minute),
881+
Update: schema.DefaultTimeout(20 * time.Minute),
882+
Delete: schema.DefaultTimeout(20 * time.Minute),
883+
},
884+
885+
Schema: map[string]*schema.Schema{
886+
"name": {
887+
Type: schema.TypeString,
888+
Required: true,
889+
ForceNew: true,
890+
Description: `A user-defined name of the certificate. Certificate names must be unique
891+
The name must be 1-64 characters long, and match the regular expression [a-zA-Z][a-zA-Z0-9_-]* which means the first character must be a letter,
892+
and all following characters must be a dash, underscore, letter or digit.`,
893+
},
894+
"description": {
895+
Type: schema.TypeString,
896+
Optional: true,
897+
Description: `A human-readable description of the resource.`,
898+
},
899+
"labels": {
900+
Type: schema.TypeMap,
901+
Optional: true,
902+
Description: `Set of label tags associated with the Certificate resource.`,
903+
Elem: &schema.Schema{Type: schema.TypeString},
904+
},
905+
"managed": {
906+
Type: schema.TypeList,
907+
Optional: true,
908+
ForceNew: true,
909+
Description: `Configuration and state of a Managed Certificate.
910+
Certificate Manager provisions and renews Managed Certificates
911+
automatically, for as long as it's authorized to do so.`,
912+
MaxItems: 1,
913+
Elem: &schema.Resource{
914+
Schema: map[string]*schema.Schema{
915+
"dns_authorizations": {
916+
Type: schema.TypeList,
917+
Optional: true,
918+
ForceNew: true,
919+
DiffSuppressFunc: ProjectNumberDiffSuppress,
920+
Description: `Authorizations that will be used for performing domain authorization`,
921+
Elem: &schema.Schema{
922+
Type: schema.TypeString,
923+
},
924+
},
925+
"domains": {
926+
Type: schema.TypeList,
927+
Optional: true,
928+
ForceNew: true,
929+
Description: `The domains for which a managed SSL certificate will be generated.
930+
Wildcard domains are only supported with DNS challenge resolution`,
931+
Elem: &schema.Schema{
932+
Type: schema.TypeString,
933+
},
934+
},
935+
"authorization_attempt_info": {
936+
Type: schema.TypeList,
937+
Computed: true,
938+
Description: `Detailed state of the latest authorization attempt for each domain
939+
specified for this Managed Certificate.`,
940+
Elem: &schema.Resource{
941+
Schema: map[string]*schema.Schema{
942+
"details": {
943+
Type: schema.TypeString,
944+
Computed: true,
945+
Description: `Human readable explanation for reaching the state. Provided to help
946+
address the configuration issues.
947+
Not guaranteed to be stable. For programmatic access use 'failure_reason' field.`,
948+
},
949+
"domain": {
950+
Type: schema.TypeString,
951+
Computed: true,
952+
Description: `Domain name of the authorization attempt.`,
953+
},
954+
"failure_reason": {
955+
Type: schema.TypeString,
956+
Computed: true,
957+
Description: `Reason for failure of the authorization attempt for the domain.`,
958+
},
959+
"state": {
960+
Type: schema.TypeString,
961+
Computed: true,
962+
Description: `State of the domain for managed certificate issuance.`,
963+
},
964+
},
965+
},
966+
},
967+
"provisioning_issue": {
968+
Type: schema.TypeList,
969+
Computed: true,
970+
Description: `Information about issues with provisioning this Managed Certificate.`,
971+
Elem: &schema.Resource{
972+
Schema: map[string]*schema.Schema{
973+
"details": {
974+
Type: schema.TypeString,
975+
Computed: true,
976+
Description: `Human readable explanation about the issue. Provided to help address
977+
the configuration issues.
978+
Not guaranteed to be stable. For programmatic access use 'reason' field.`,
979+
},
980+
"reason": {
981+
Type: schema.TypeString,
982+
Computed: true,
983+
Description: `Reason for provisioning failures.`,
984+
},
985+
},
986+
},
987+
},
988+
"state": {
989+
Type: schema.TypeString,
990+
Computed: true,
991+
Description: `A state of this Managed Certificate.`,
992+
},
993+
},
994+
},
995+
ExactlyOneOf: []string{"self_managed", "managed"},
996+
},
997+
"scope": {
998+
Type: schema.TypeString,
999+
Optional: true,
1000+
ForceNew: true,
1001+
DiffSuppressFunc: certManagerDefaultScopeDiffSuppress,
1002+
Description: `The scope of the certificate.
1003+
1004+
DEFAULT: Certificates with default scope are served from core Google data centers.
1005+
If unsure, choose this option.
1006+
1007+
EDGE_CACHE: Certificates with scope EDGE_CACHE are special-purposed certificates,
1008+
served from non-core Google data centers.
1009+
Currently allowed only for managed certificates.`,
1010+
Default: "DEFAULT",
1011+
},
1012+
"self_managed": {
1013+
Type: schema.TypeList,
1014+
Optional: true,
1015+
ForceNew: true,
1016+
Description: `Certificate data for a SelfManaged Certificate.
1017+
SelfManaged Certificates are uploaded by the user. Updating such
1018+
certificates before they expire remains the user's responsibility.`,
1019+
MaxItems: 1,
1020+
Elem: &schema.Resource{
1021+
Schema: map[string]*schema.Schema{
1022+
"certificate_pem": {
1023+
Type: schema.TypeString,
1024+
Optional: true,
1025+
Deprecated: "Deprecated in favor of `pem_certificate`",
1026+
Description: `**Deprecated** The certificate chain in PEM-encoded form.
1027+
1028+
Leaf certificate comes first, followed by intermediate ones if any.`,
1029+
Sensitive: true,
1030+
ExactlyOneOf: []string{"self_managed.0.certificate_pem", "self_managed.0.pem_certificate"},
1031+
},
1032+
"pem_certificate": {
1033+
Type: schema.TypeString,
1034+
Optional: true,
1035+
Description: `The certificate chain in PEM-encoded form.
1036+
1037+
Leaf certificate comes first, followed by intermediate ones if any.`,
1038+
ExactlyOneOf: []string{"self_managed.0.certificate_pem", "self_managed.0.pem_certificate"},
1039+
},
1040+
"pem_private_key": {
1041+
Type: schema.TypeString,
1042+
Optional: true,
1043+
Description: `The private key of the leaf certificate in PEM-encoded form.`,
1044+
Sensitive: true,
1045+
ExactlyOneOf: []string{"self_managed.0.private_key_pem", "self_managed.0.pem_private_key"},
1046+
},
1047+
"private_key_pem": {
1048+
Type: schema.TypeString,
1049+
Optional: true,
1050+
Deprecated: "Deprecated in favor of `pem_private_key`",
1051+
Description: `**Deprecated** The private key of the leaf certificate in PEM-encoded form.`,
1052+
Sensitive: true,
1053+
ExactlyOneOf: []string{"self_managed.0.private_key_pem", "self_managed.0.pem_private_key"},
1054+
},
1055+
},
1056+
},
1057+
ExactlyOneOf: []string{"self_managed", "managed"},
1058+
},
1059+
"project": {
1060+
Type: schema.TypeString,
1061+
Optional: true,
1062+
Computed: true,
1063+
ForceNew: true,
1064+
},
1065+
},
1066+
UseJSONNumber: true,
1067+
}
1068+
}

0 commit comments

Comments
 (0)