mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-03 01:01:06 +00:00
Beginnings of App Engine app support.
This should have all the code, but who really knows if it works or not, tbh.
This commit is contained in:
parent
07ff71f287
commit
765d9af0a3
74
google/appengine_operation.go
Normal file
74
google/appengine_operation.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
|
||||||
|
"google.golang.org/api/appengine/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AppEngineOperationWaiter struct {
|
||||||
|
Service *appengine.APIService
|
||||||
|
Op *appengine.Operation
|
||||||
|
AppId string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *AppEngineOperationWaiter) RefreshFunc() resource.StateRefreshFunc {
|
||||||
|
return func() (interface{}, string, error) {
|
||||||
|
op, err := w.Service.Apps.Operations.Get(w.AppId, w.Op.Name).Do()
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Got %v when asking for operation %q", op.Done, w.Op.Name)
|
||||||
|
return op, strconv.FormatBool(op.Done), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *AppEngineOperationWaiter) Conf() *resource.StateChangeConf {
|
||||||
|
return &resource.StateChangeConf{
|
||||||
|
Pending: []string{"false"},
|
||||||
|
Target: []string{"true"},
|
||||||
|
Refresh: w.RefreshFunc(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppEngineOperationError wraps appengine.Status and implements the
|
||||||
|
// error interface so it can be returned.
|
||||||
|
type AppEngineOperationError appengine.Status
|
||||||
|
|
||||||
|
func (e AppEngineOperationError) Error() string {
|
||||||
|
return e.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
func appEngineOperationWait(client *appengine.APIService, op *appengine.Operation, appId, activity string) error {
|
||||||
|
return appEngineOperationWaitTime(client, op, appId, activity, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appEngineOperationWaitTime(client *appengine.APIService, op *appengine.Operation, appId, activity string, timeoutMin int) error {
|
||||||
|
w := &AppEngineOperationWaiter{
|
||||||
|
Service: client,
|
||||||
|
Op: op,
|
||||||
|
AppId: appId,
|
||||||
|
}
|
||||||
|
|
||||||
|
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.(*appengine.Operation)
|
||||||
|
if resultOp.Error != nil {
|
||||||
|
return AppEngineOperationError(*resultOp.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -15,6 +15,7 @@ import (
|
|||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
"golang.org/x/oauth2/google"
|
"golang.org/x/oauth2/google"
|
||||||
"golang.org/x/oauth2/jwt"
|
"golang.org/x/oauth2/jwt"
|
||||||
|
appengine "google.golang.org/api/appengine/v1"
|
||||||
"google.golang.org/api/bigquery/v2"
|
"google.golang.org/api/bigquery/v2"
|
||||||
"google.golang.org/api/cloudbilling/v1"
|
"google.golang.org/api/cloudbilling/v1"
|
||||||
"google.golang.org/api/cloudfunctions/v1"
|
"google.golang.org/api/cloudfunctions/v1"
|
||||||
@ -76,6 +77,7 @@ type Config struct {
|
|||||||
clientBigQuery *bigquery.Service
|
clientBigQuery *bigquery.Service
|
||||||
clientCloudFunctions *cloudfunctions.Service
|
clientCloudFunctions *cloudfunctions.Service
|
||||||
clientCloudIoT *cloudiot.Service
|
clientCloudIoT *cloudiot.Service
|
||||||
|
clientAppEngine *appengine.APIService
|
||||||
|
|
||||||
bigtableClientFactory *BigtableClientFactory
|
bigtableClientFactory *BigtableClientFactory
|
||||||
}
|
}
|
||||||
@ -315,6 +317,13 @@ func (c *Config) loadAndValidate() error {
|
|||||||
}
|
}
|
||||||
c.clientCloudIoT.UserAgent = userAgent
|
c.clientCloudIoT.UserAgent = userAgent
|
||||||
|
|
||||||
|
log.Printf("[INFO] Instantiating App Engine Client...")
|
||||||
|
c.clientAppEngine, err = appengine.New(client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.clientAppEngine.UserAgent = userAgent
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package google
|
package google
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -9,6 +10,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/helper/validation"
|
||||||
|
appengine "google.golang.org/api/appengine/v1"
|
||||||
"google.golang.org/api/cloudbilling/v1"
|
"google.golang.org/api/cloudbilling/v1"
|
||||||
"google.golang.org/api/cloudresourcemanager/v1"
|
"google.golang.org/api/cloudresourcemanager/v1"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
@ -28,7 +31,8 @@ func resourceGoogleProject() *schema.Resource {
|
|||||||
Importer: &schema.ResourceImporter{
|
Importer: &schema.ResourceImporter{
|
||||||
State: resourceProjectImportState,
|
State: resourceProjectImportState,
|
||||||
},
|
},
|
||||||
MigrateState: resourceGoogleProjectMigrateState,
|
MigrateState: resourceGoogleProjectMigrateState,
|
||||||
|
CustomizeDiff: resourceGoogleProjectCustomizeDiff,
|
||||||
|
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"project_id": &schema.Schema{
|
"project_id": &schema.Schema{
|
||||||
@ -86,10 +90,161 @@ func resourceGoogleProject() *schema.Resource {
|
|||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
Set: schema.HashString,
|
Set: schema.HashString,
|
||||||
},
|
},
|
||||||
|
"app_engine": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
Elem: appEngineResource(),
|
||||||
|
MaxItems: 1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func appEngineResource() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"url_dispatch_rule": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
Elem: appEngineURLDispatchRuleResource(),
|
||||||
|
},
|
||||||
|
"auth_domain": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"location_id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
ValidateFunc: validation.StringInSlice([]string{
|
||||||
|
"northamerica-northeast1",
|
||||||
|
"us-central",
|
||||||
|
"us-east1",
|
||||||
|
"us-east4",
|
||||||
|
"southamerica-east1",
|
||||||
|
"europe-west",
|
||||||
|
"europe-west2",
|
||||||
|
"europe-west3",
|
||||||
|
"asia-northeast1",
|
||||||
|
"asia-south1",
|
||||||
|
"australia-southeast1",
|
||||||
|
}, false),
|
||||||
|
},
|
||||||
|
"code_bucket": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"default_cookie_expiration_seconds": &schema.Schema{
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"serving_status": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"default_hostname": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"default_bucket": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"iap": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
MaxItems: 1,
|
||||||
|
Elem: appEngineIAPResource(),
|
||||||
|
},
|
||||||
|
"gcr_domain": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"feature_settings": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
MaxItems: 1,
|
||||||
|
Elem: appEngineFeatureSettingsResource(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func appEngineURLDispatchRuleResource() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"domain": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"path": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"service": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func appEngineIAPResource() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"enabled": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"oauth2_client_id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"oauth2_client_secret": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
Sensitive: true,
|
||||||
|
},
|
||||||
|
"oauth2_client_secret_sha256": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Sensitive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func appEngineFeatureSettingsResource() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"split_health_checks": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceGoogleProjectCustomizeDiff(diff *schema.ResourceDiff, meta interface{}) error {
|
||||||
|
// don't need to check if changed, the call is a no-op/error if there's no change
|
||||||
|
diff.ForceNew("app_engine.#")
|
||||||
|
|
||||||
|
// force a change to client secret if it doesn't match its sha
|
||||||
|
if !diff.HasChange("app_engine.0.iap.0.oauth2_client_secret") {
|
||||||
|
sha := sha256.Sum256([]byte(diff.Get("app_engine.0.iap.0.oauth2_client_secret").(string)))
|
||||||
|
if string(sha[:]) != diff.Get("app_engine.0.iap.0.oauth2_client_secret_sha256").(string) {
|
||||||
|
diff.SetNew("app_engine.0.iap.0.oauth2_client_secret", diff.Get("app_engine.0.iap.0.oauth2_client_secret"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func resourceGoogleProjectCreate(d *schema.ResourceData, meta interface{}) error {
|
func resourceGoogleProjectCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
config := meta.(*Config)
|
config := meta.(*Config)
|
||||||
|
|
||||||
@ -153,6 +308,30 @@ func resourceGoogleProjectCreate(d *schema.ResourceData, meta interface{}) error
|
|||||||
return fmt.Errorf("Error deleting default network in project %s: %s", project.ProjectId, err)
|
return fmt.Errorf("Error deleting default network in project %s: %s", project.ProjectId, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set up App Engine, too
|
||||||
|
if len(d.Get("app_engine").([]interface{})) > 0 {
|
||||||
|
// enable the app engine APIs so we can create stuff
|
||||||
|
if err = enableService("appengine.googleapis.com", project.ProjectId, config); err != nil {
|
||||||
|
return fmt.Errorf("Error enabling the App Engine Admin API required to configure App Engine applications: %s", err)
|
||||||
|
}
|
||||||
|
app, err := expandAppEngineApp(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if app != nil {
|
||||||
|
op, err := config.clientAppEngine.Apps.Create(app).Do()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating App Engine application: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the operation to complete
|
||||||
|
waitErr := appEngineOperationWait(config.clientAppEngine, op, app.Id, "App Engine app to create")
|
||||||
|
if waitErr != nil {
|
||||||
|
return waitErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,6 +386,22 @@ func resourceGoogleProjectRead(d *schema.ResourceData, meta interface{}) error {
|
|||||||
}
|
}
|
||||||
d.Set("billing_account", _ba)
|
d.Set("billing_account", _ba)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read the App Engine app
|
||||||
|
if d.Get("app_engine.#").(int) > 0 {
|
||||||
|
app, err := config.clientAppEngine.Apps.Get(pid).Do()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error retrieving App Engine application %q: %s", pid, err.Error())
|
||||||
|
}
|
||||||
|
appBlocks, err := flattenAppEngineApp(app)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error serializing App Engine app: %s", err.Error())
|
||||||
|
}
|
||||||
|
err = d.Set("app_engine", appBlocks)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error setting App Engine application in state. This is a bug, please report it at https://github.com/terraform-providers/terraform-provider-google/issues")
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,6 +503,25 @@ func resourceGoogleProjectUpdate(d *schema.ResourceData, meta interface{}) error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error updating project %q: %s", project_name, err)
|
return fmt.Errorf("Error updating project %q: %s", project_name, err)
|
||||||
}
|
}
|
||||||
|
d.SetPartial("labels")
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("app_engine") {
|
||||||
|
// don't need to worry about case where block is removed; custom diff does that
|
||||||
|
// for us
|
||||||
|
app, err := expandAppEngineApp(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
op, err := config.clientAppEngine.Apps.Patch(p.ProjectId, app).Do()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error updating App Engine application %q: %s", p.ProjectId, err.Error())
|
||||||
|
}
|
||||||
|
waitErr := appEngineOperationWait(config.clientAppEngine, op, p.ProjectId, "App Engine app to update")
|
||||||
|
if waitErr != nil {
|
||||||
|
return waitErr
|
||||||
|
}
|
||||||
|
d.SetPartial("app_engine")
|
||||||
}
|
}
|
||||||
d.Partial(false)
|
d.Partial(false)
|
||||||
|
|
||||||
@ -399,3 +613,142 @@ func updateProjectBillingAccount(d *schema.ResourceData, config *Config) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func expandAppEngineApp(d *schema.ResourceData) (*appengine.Application, error) {
|
||||||
|
blocks := d.Get("app_engine").([]interface{})
|
||||||
|
if len(blocks) < 1 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if len(blocks) > 1 {
|
||||||
|
return nil, fmt.Errorf("only one app_engine block may be defined per project")
|
||||||
|
}
|
||||||
|
result := &appengine.Application{
|
||||||
|
AuthDomain: d.Get("app_engine.0.auth_domain").(string),
|
||||||
|
LocationId: d.Get("app_engine.0.location_id").(string),
|
||||||
|
Id: d.Get("project_id").(string),
|
||||||
|
GcrDomain: d.Get("gcr_domain").(string),
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOkExists("app_engine.0.default_cookie_expiration_seconds"); ok {
|
||||||
|
result.DefaultCookieExpiration = strconv.FormatFloat(v.(float64), 'f', 9, 64) + "s"
|
||||||
|
}
|
||||||
|
iap, err := expandAppEngineIAP(d, "app_engine.0.")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.Iap = iap
|
||||||
|
featureSettings, err := expandAppEngineFeatureSettings(d, "app_engine.0.")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.FeatureSettings = featureSettings
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func flattenAppEngineApp(app *appengine.Application) ([]map[string]interface{}, error) {
|
||||||
|
result := map[string]interface{}{
|
||||||
|
"auth_domain": app.AuthDomain,
|
||||||
|
"code_bucket": app.CodeBucket,
|
||||||
|
"default_bucket": app.DefaultBucket,
|
||||||
|
"default_hostname": app.DefaultHostname,
|
||||||
|
"location_id": app.LocationId,
|
||||||
|
"name": app.Name,
|
||||||
|
"serving_status": app.ServingStatus,
|
||||||
|
}
|
||||||
|
if app.DefaultCookieExpiration != "" {
|
||||||
|
seconds := strings.TrimSuffix(app.DefaultCookieExpiration, "s")
|
||||||
|
exp, err := strconv.ParseFloat(seconds, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid default cookie expiration: %s", err.Error())
|
||||||
|
}
|
||||||
|
result["default_cookie_expiration_seconds"] = exp
|
||||||
|
}
|
||||||
|
dispatchRules, err := flattenAppEngineDispatchRules(app.DispatchRules)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result["dispatch_rule"] = dispatchRules
|
||||||
|
featureSettings, err := flattenAppEngineFeatureSettings(app.FeatureSettings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result["feature_settings"] = featureSettings
|
||||||
|
iap, err := flattenAppEngineIAP(app.Iap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result["iap"] = iap
|
||||||
|
return []map[string]interface{}{result}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func expandAppEngineIAP(d *schema.ResourceData, prefix string) (*appengine.IdentityAwareProxy, error) {
|
||||||
|
blocks := d.Get(prefix + "iap").([]interface{})
|
||||||
|
if len(blocks) < 1 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if len(blocks) > 1 {
|
||||||
|
return nil, fmt.Errorf("only one iap block may be defined per app")
|
||||||
|
}
|
||||||
|
if d.Get(prefix+"iap.0.oauth2_client_id").(string) == "" && d.Get(prefix+"iap.0.enabled").(bool) {
|
||||||
|
return nil, fmt.Errorf("oauth2_client_id must be set if the IAP is enabled")
|
||||||
|
}
|
||||||
|
if d.Get(prefix+"iap.0.oauth2_client_secret") == "" && d.Get(prefix+"iap.0.enabled").(bool) {
|
||||||
|
return nil, fmt.Errorf("oauth2_client_secret must be set if the IAP is enabled")
|
||||||
|
}
|
||||||
|
return &appengine.IdentityAwareProxy{
|
||||||
|
Enabled: d.Get(prefix + "iap.0.enabled").(bool),
|
||||||
|
Oauth2ClientId: d.Get(prefix + "iap.0.oauth2_client_id").(string),
|
||||||
|
Oauth2ClientSecret: d.Get(prefix + "iap.0.oauth2_client_secret").(string),
|
||||||
|
// force send enabled, so if it's set to false, IAP still gets turned off
|
||||||
|
ForceSendFields: []string{"Enabled"},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func flattenAppEngineIAP(iap *appengine.IdentityAwareProxy) ([]map[string]interface{}, error) {
|
||||||
|
if iap == nil {
|
||||||
|
return []map[string]interface{}{}, nil
|
||||||
|
}
|
||||||
|
result := map[string]interface{}{
|
||||||
|
"enabled": iap.Enabled,
|
||||||
|
"oauth2_client_id": iap.Oauth2ClientId,
|
||||||
|
"oauth2_client_secret_sha256": iap.Oauth2ClientSecretSha256,
|
||||||
|
// don't set client secret, it's not returned by the API
|
||||||
|
}
|
||||||
|
return []map[string]interface{}{result}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func expandAppEngineFeatureSettings(d *schema.ResourceData, prefix string) (*appengine.FeatureSettings, error) {
|
||||||
|
blocks := d.Get(prefix + "feature_settings").([]interface{})
|
||||||
|
if len(blocks) < 1 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if len(blocks) > 1 {
|
||||||
|
return nil, fmt.Errorf("only one feature_settings block may be defined per app")
|
||||||
|
}
|
||||||
|
return &appengine.FeatureSettings{
|
||||||
|
SplitHealthChecks: d.Get(prefix + "feature_settings.0.split_health_checks").(bool),
|
||||||
|
// force send SplitHealthChecks, so if it's set to false it still gets disabled
|
||||||
|
ForceSendFields: []string{"SplitHealthChecks"},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func flattenAppEngineFeatureSettings(settings *appengine.FeatureSettings) ([]map[string]interface{}, error) {
|
||||||
|
if settings == nil {
|
||||||
|
return []map[string]interface{}{}, nil
|
||||||
|
}
|
||||||
|
result := map[string]interface{}{
|
||||||
|
"split_health_checks": settings.SplitHealthChecks,
|
||||||
|
}
|
||||||
|
return []map[string]interface{}{result}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func flattenAppEngineDispatchRules(rules []*appengine.UrlDispatchRule) ([]map[string]interface{}, error) {
|
||||||
|
results := make([]map[string]interface{}, 0, len(rules))
|
||||||
|
for _, rule := range rules {
|
||||||
|
results = append(results, map[string]interface{}{
|
||||||
|
"domain": rule.Domain,
|
||||||
|
"path": rule.Path,
|
||||||
|
"service": rule.Service,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user