diff --git a/.changelog/4818.txt b/.changelog/4818.txt new file mode 100644 index 0000000000..a5e787700f --- /dev/null +++ b/.changelog/4818.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +`google_dialogflow_cx_agent` +``` diff --git a/google-beta/config.go b/google-beta/config.go index 3d39acba97..4a48f64dd1 100644 --- a/google-beta/config.go +++ b/google-beta/config.go @@ -112,6 +112,7 @@ type Config struct { DatastoreBasePath string DeploymentManagerBasePath string DialogflowBasePath string + DialogflowCXBasePath string DNSBasePath string EssentialContactsBasePath string FilestoreBasePath string @@ -209,6 +210,7 @@ var DataprocMetastoreDefaultBasePath = "https://metastore.googleapis.com/v1beta/ var DatastoreDefaultBasePath = "https://datastore.googleapis.com/v1/" var DeploymentManagerDefaultBasePath = "https://www.googleapis.com/deploymentmanager/v2/" var DialogflowDefaultBasePath = "https://dialogflow.googleapis.com/v2/" +var DialogflowCXDefaultBasePath = "https://{{location}}-dialogflow.googleapis.com/v3/" var DNSDefaultBasePath = "https://dns.googleapis.com/dns/v1beta2/" var EssentialContactsDefaultBasePath = "https://essentialcontacts.googleapis.com/v1beta1/" var FilestoreDefaultBasePath = "https://file.googleapis.com/v1beta1/" @@ -1034,6 +1036,7 @@ func ConfigureBasePaths(c *Config) { c.DatastoreBasePath = DatastoreDefaultBasePath c.DeploymentManagerBasePath = DeploymentManagerDefaultBasePath c.DialogflowBasePath = DialogflowDefaultBasePath + c.DialogflowCXBasePath = DialogflowCXDefaultBasePath c.DNSBasePath = DNSDefaultBasePath c.EssentialContactsBasePath = EssentialContactsDefaultBasePath c.FilestoreBasePath = FilestoreDefaultBasePath diff --git a/google-beta/provider.go b/google-beta/provider.go index fa1b59536c..6c1117fcba 100644 --- a/google-beta/provider.go +++ b/google-beta/provider.go @@ -383,6 +383,14 @@ func Provider() *schema.Provider { "GOOGLE_DIALOGFLOW_CUSTOM_ENDPOINT", }, DialogflowDefaultBasePath), }, + "dialogflow_cx_custom_endpoint": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateCustomEndpoint, + DefaultFunc: schema.MultiEnvDefaultFunc([]string{ + "GOOGLE_DIALOGFLOW_CX_CUSTOM_ENDPOINT", + }, DialogflowCXDefaultBasePath), + }, "dns_custom_endpoint": { Type: schema.TypeString, Optional: true, @@ -839,9 +847,9 @@ func Provider() *schema.Provider { return provider } -// Generated resources: 223 +// Generated resources: 224 // Generated IAM resources: 117 -// Total generated resources: 340 +// Total generated resources: 341 func ResourceMap() map[string]*schema.Resource { resourceMap, _ := ResourceMapWithErrors() return resourceMap @@ -1042,6 +1050,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) { "google_dialogflow_intent": resourceDialogflowIntent(), "google_dialogflow_entity_type": resourceDialogflowEntityType(), "google_dialogflow_fulfillment": resourceDialogflowFulfillment(), + "google_dialogflow_cx_agent": resourceDialogflowCXAgent(), "google_dns_managed_zone": resourceDNSManagedZone(), "google_dns_policy": resourceDNSPolicy(), "google_dns_record_set": resourceDNSResourceDnsRecordSet(), @@ -1432,6 +1441,7 @@ func providerConfigure(ctx context.Context, d *schema.ResourceData, p *schema.Pr config.DatastoreBasePath = d.Get("datastore_custom_endpoint").(string) config.DeploymentManagerBasePath = d.Get("deployment_manager_custom_endpoint").(string) config.DialogflowBasePath = d.Get("dialogflow_custom_endpoint").(string) + config.DialogflowCXBasePath = d.Get("dialogflow_cx_custom_endpoint").(string) config.DNSBasePath = d.Get("dns_custom_endpoint").(string) config.EssentialContactsBasePath = d.Get("essential_contacts_custom_endpoint").(string) config.FilestoreBasePath = d.Get("filestore_custom_endpoint").(string) diff --git a/google-beta/resource_dialogflow_cx_agent.go b/google-beta/resource_dialogflow_cx_agent.go new file mode 100644 index 0000000000..15e4cb1445 --- /dev/null +++ b/google-beta/resource_dialogflow_cx_agent.go @@ -0,0 +1,641 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "fmt" + "log" + "reflect" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceDialogflowCXAgent() *schema.Resource { + return &schema.Resource{ + Create: resourceDialogflowCXAgentCreate, + Read: resourceDialogflowCXAgentRead, + Update: resourceDialogflowCXAgentUpdate, + Delete: resourceDialogflowCXAgentDelete, + + Importer: &schema.ResourceImporter{ + State: resourceDialogflowCXAgentImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(40 * time.Minute), + Update: schema.DefaultTimeout(40 * time.Minute), + Delete: schema.DefaultTimeout(4 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "default_language_code": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The default language of the agent as a language tag. [See Language Support](https://cloud.google.com/dialogflow/cx/docs/reference/language) +for a list of the currently supported language codes. This field cannot be updated after creation.`, + }, + "display_name": { + Type: schema.TypeString, + Required: true, + Description: `The human-readable name of the agent, unique within the location.`, + }, + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the location this agent is located in. + +~> **Note:** The first time you are deploying an Agent in your project you must configure location settings. + This is a one time step but at the moment you can only [configure location settings](https://cloud.google.com/dialogflow/cx/docs/concept/region#location-settings) via the Dialogflow CX console. + Another options is to use global location so you don't need to manually configure location settings.`, + }, + "time_zone": { + Type: schema.TypeString, + Required: true, + Description: `The time zone of this agent from the [time zone database](https://www.iana.org/time-zones), e.g., America/New_York, +Europe/Paris.`, + }, + "avatar_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The URI of the agent's avatar. Avatars are used throughout the Dialogflow console and in the self-hosted Web Demo integration.`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(0, 500), + Description: `The description of this agent. The maximum length is 500 characters. If exceeded, the request is rejected.`, + }, + "enable_spell_correction": { + Type: schema.TypeBool, + Optional: true, + Description: `Indicates if automatic spell correction is enabled in detect intent requests.`, + }, + "enable_stackdriver_logging": { + Type: schema.TypeBool, + Optional: true, + Description: `Determines whether this agent should log conversation queries.`, + }, + "security_settings": { + Type: schema.TypeString, + Optional: true, + Description: `Name of the SecuritySettings reference for the agent. Format: projects//locations//securitySettings/.`, + }, + "speech_to_text_settings": { + Type: schema.TypeList, + Optional: true, + Description: `Settings related to speech recognition.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_speech_adaptation": { + Type: schema.TypeBool, + Optional: true, + Description: `Whether to use speech adaptation for speech recognition.`, + }, + }, + }, + }, + "supported_language_codes": { + Type: schema.TypeList, + Optional: true, + Description: `The list of all languages supported by this agent (except for the default_language_code).`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `The unique identifier of the agent.`, + }, + "start_flow": { + Type: schema.TypeString, + Computed: true, + Description: `Name of the start flow in this agent. A start flow will be automatically created when the agent is created, and can only be deleted by deleting the agent. Format: projects//locations//agents//flows/.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func resourceDialogflowCXAgentCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + displayNameProp, err := expandDialogflowCXAgentDisplayName(d.Get("display_name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("display_name"); !isEmptyValue(reflect.ValueOf(displayNameProp)) && (ok || !reflect.DeepEqual(v, displayNameProp)) { + obj["displayName"] = displayNameProp + } + defaultLanguageCodeProp, err := expandDialogflowCXAgentDefaultLanguageCode(d.Get("default_language_code"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("default_language_code"); !isEmptyValue(reflect.ValueOf(defaultLanguageCodeProp)) && (ok || !reflect.DeepEqual(v, defaultLanguageCodeProp)) { + obj["defaultLanguageCode"] = defaultLanguageCodeProp + } + supportedLanguageCodesProp, err := expandDialogflowCXAgentSupportedLanguageCodes(d.Get("supported_language_codes"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("supported_language_codes"); !isEmptyValue(reflect.ValueOf(supportedLanguageCodesProp)) && (ok || !reflect.DeepEqual(v, supportedLanguageCodesProp)) { + obj["supportedLanguageCodes"] = supportedLanguageCodesProp + } + timeZoneProp, err := expandDialogflowCXAgentTimeZone(d.Get("time_zone"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("time_zone"); !isEmptyValue(reflect.ValueOf(timeZoneProp)) && (ok || !reflect.DeepEqual(v, timeZoneProp)) { + obj["timeZone"] = timeZoneProp + } + descriptionProp, err := expandDialogflowCXAgentDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + avatarUriProp, err := expandDialogflowCXAgentAvatarUri(d.Get("avatar_uri"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("avatar_uri"); !isEmptyValue(reflect.ValueOf(avatarUriProp)) && (ok || !reflect.DeepEqual(v, avatarUriProp)) { + obj["avatarUri"] = avatarUriProp + } + speechToTextSettingsProp, err := expandDialogflowCXAgentSpeechToTextSettings(d.Get("speech_to_text_settings"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("speech_to_text_settings"); !isEmptyValue(reflect.ValueOf(speechToTextSettingsProp)) && (ok || !reflect.DeepEqual(v, speechToTextSettingsProp)) { + obj["speechToTextSettings"] = speechToTextSettingsProp + } + securitySettingsProp, err := expandDialogflowCXAgentSecuritySettings(d.Get("security_settings"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("security_settings"); !isEmptyValue(reflect.ValueOf(securitySettingsProp)) && (ok || !reflect.DeepEqual(v, securitySettingsProp)) { + obj["securitySettings"] = securitySettingsProp + } + enableStackdriverLoggingProp, err := expandDialogflowCXAgentEnableStackdriverLogging(d.Get("enable_stackdriver_logging"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("enable_stackdriver_logging"); !isEmptyValue(reflect.ValueOf(enableStackdriverLoggingProp)) && (ok || !reflect.DeepEqual(v, enableStackdriverLoggingProp)) { + obj["enableStackdriverLogging"] = enableStackdriverLoggingProp + } + enableSpellCorrectionProp, err := expandDialogflowCXAgentEnableSpellCorrection(d.Get("enable_spell_correction"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("enable_spell_correction"); !isEmptyValue(reflect.ValueOf(enableSpellCorrectionProp)) && (ok || !reflect.DeepEqual(v, enableSpellCorrectionProp)) { + obj["enableSpellCorrection"] = enableSpellCorrectionProp + } + + url, err := replaceVars(d, config, "{{DialogflowCXBasePath}}projects/{{project}}/locations/{{location}}/agents") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new Agent: %#v", obj) + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for Agent: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := sendRequestWithTimeout(config, "POST", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return fmt.Errorf("Error creating Agent: %s", err) + } + if err := d.Set("name", flattenDialogflowCXAgentName(res["name"], d, config)); err != nil { + return fmt.Errorf(`Error setting computed identity field "name": %s`, err) + } + + // Store the ID now + id, err := replaceVars(d, config, "projects/{{project}}/locations/{{location}}/agents/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + log.Printf("[DEBUG] Finished creating Agent %q: %#v", d.Id(), res) + + return resourceDialogflowCXAgentRead(d, meta) +} + +func resourceDialogflowCXAgentRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + url, err := replaceVars(d, config, "{{DialogflowCXBasePath}}projects/{{project}}/locations/{{location}}/agents/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for Agent: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := sendRequest(config, "GET", billingProject, url, userAgent, nil) + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("DialogflowCXAgent %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading Agent: %s", err) + } + + if err := d.Set("name", flattenDialogflowCXAgentName(res["name"], d, config)); err != nil { + return fmt.Errorf("Error reading Agent: %s", err) + } + if err := d.Set("display_name", flattenDialogflowCXAgentDisplayName(res["displayName"], d, config)); err != nil { + return fmt.Errorf("Error reading Agent: %s", err) + } + if err := d.Set("default_language_code", flattenDialogflowCXAgentDefaultLanguageCode(res["defaultLanguageCode"], d, config)); err != nil { + return fmt.Errorf("Error reading Agent: %s", err) + } + if err := d.Set("supported_language_codes", flattenDialogflowCXAgentSupportedLanguageCodes(res["supportedLanguageCodes"], d, config)); err != nil { + return fmt.Errorf("Error reading Agent: %s", err) + } + if err := d.Set("time_zone", flattenDialogflowCXAgentTimeZone(res["timeZone"], d, config)); err != nil { + return fmt.Errorf("Error reading Agent: %s", err) + } + if err := d.Set("description", flattenDialogflowCXAgentDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading Agent: %s", err) + } + if err := d.Set("avatar_uri", flattenDialogflowCXAgentAvatarUri(res["avatarUri"], d, config)); err != nil { + return fmt.Errorf("Error reading Agent: %s", err) + } + if err := d.Set("speech_to_text_settings", flattenDialogflowCXAgentSpeechToTextSettings(res["speechToTextSettings"], d, config)); err != nil { + return fmt.Errorf("Error reading Agent: %s", err) + } + if err := d.Set("start_flow", flattenDialogflowCXAgentStartFlow(res["startFlow"], d, config)); err != nil { + return fmt.Errorf("Error reading Agent: %s", err) + } + if err := d.Set("security_settings", flattenDialogflowCXAgentSecuritySettings(res["securitySettings"], d, config)); err != nil { + return fmt.Errorf("Error reading Agent: %s", err) + } + if err := d.Set("enable_stackdriver_logging", flattenDialogflowCXAgentEnableStackdriverLogging(res["enableStackdriverLogging"], d, config)); err != nil { + return fmt.Errorf("Error reading Agent: %s", err) + } + if err := d.Set("enable_spell_correction", flattenDialogflowCXAgentEnableSpellCorrection(res["enableSpellCorrection"], d, config)); err != nil { + return fmt.Errorf("Error reading Agent: %s", err) + } + + return nil +} + +func resourceDialogflowCXAgentUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for Agent: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + displayNameProp, err := expandDialogflowCXAgentDisplayName(d.Get("display_name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("display_name"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, displayNameProp)) { + obj["displayName"] = displayNameProp + } + supportedLanguageCodesProp, err := expandDialogflowCXAgentSupportedLanguageCodes(d.Get("supported_language_codes"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("supported_language_codes"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, supportedLanguageCodesProp)) { + obj["supportedLanguageCodes"] = supportedLanguageCodesProp + } + timeZoneProp, err := expandDialogflowCXAgentTimeZone(d.Get("time_zone"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("time_zone"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, timeZoneProp)) { + obj["timeZone"] = timeZoneProp + } + descriptionProp, err := expandDialogflowCXAgentDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + avatarUriProp, err := expandDialogflowCXAgentAvatarUri(d.Get("avatar_uri"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("avatar_uri"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, avatarUriProp)) { + obj["avatarUri"] = avatarUriProp + } + speechToTextSettingsProp, err := expandDialogflowCXAgentSpeechToTextSettings(d.Get("speech_to_text_settings"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("speech_to_text_settings"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, speechToTextSettingsProp)) { + obj["speechToTextSettings"] = speechToTextSettingsProp + } + securitySettingsProp, err := expandDialogflowCXAgentSecuritySettings(d.Get("security_settings"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("security_settings"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, securitySettingsProp)) { + obj["securitySettings"] = securitySettingsProp + } + enableStackdriverLoggingProp, err := expandDialogflowCXAgentEnableStackdriverLogging(d.Get("enable_stackdriver_logging"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("enable_stackdriver_logging"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, enableStackdriverLoggingProp)) { + obj["enableStackdriverLogging"] = enableStackdriverLoggingProp + } + enableSpellCorrectionProp, err := expandDialogflowCXAgentEnableSpellCorrection(d.Get("enable_spell_correction"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("enable_spell_correction"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, enableSpellCorrectionProp)) { + obj["enableSpellCorrection"] = enableSpellCorrectionProp + } + + url, err := replaceVars(d, config, "{{DialogflowCXBasePath}}projects/{{project}}/locations/{{location}}/agents/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating Agent %q: %#v", d.Id(), obj) + updateMask := []string{} + + if d.HasChange("display_name") { + updateMask = append(updateMask, "displayName") + } + + if d.HasChange("supported_language_codes") { + updateMask = append(updateMask, "supportedLanguageCodes") + } + + if d.HasChange("time_zone") { + updateMask = append(updateMask, "timeZone") + } + + if d.HasChange("description") { + updateMask = append(updateMask, "description") + } + + if d.HasChange("avatar_uri") { + updateMask = append(updateMask, "avatarUri") + } + + if d.HasChange("speech_to_text_settings") { + updateMask = append(updateMask, "speechToTextSettings") + } + + if d.HasChange("security_settings") { + updateMask = append(updateMask, "securitySettings") + } + + if d.HasChange("enable_stackdriver_logging") { + updateMask = append(updateMask, "enableStackdriverLogging") + } + + if d.HasChange("enable_spell_correction") { + updateMask = append(updateMask, "enableSpellCorrection") + } + // updateMask is a URL parameter but not present in the schema, so replaceVars + // won't set it + url, err = addQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := sendRequestWithTimeout(config, "PATCH", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return fmt.Errorf("Error updating Agent %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating Agent %q: %#v", d.Id(), res) + } + + return resourceDialogflowCXAgentRead(d, meta) +} + +func resourceDialogflowCXAgentDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for Agent: %s", err) + } + billingProject = project + + url, err := replaceVars(d, config, "{{DialogflowCXBasePath}}projects/{{project}}/locations/{{location}}/agents/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + log.Printf("[DEBUG] Deleting Agent %q", d.Id()) + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := sendRequestWithTimeout(config, "DELETE", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return handleNotFoundError(err, d, "Agent") + } + + log.Printf("[DEBUG] Finished deleting Agent %q: %#v", d.Id(), res) + return nil +} + +func resourceDialogflowCXAgentImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + if err := parseImportId([]string{ + "projects/(?P[^/]+)/locations/(?P[^/]+)/agents/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := replaceVars(d, config, "projects/{{project}}/locations/{{location}}/agents/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenDialogflowCXAgentName(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return v + } + return NameFromSelfLinkStateFunc(v) +} + +func flattenDialogflowCXAgentDisplayName(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDialogflowCXAgentDefaultLanguageCode(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDialogflowCXAgentSupportedLanguageCodes(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDialogflowCXAgentTimeZone(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDialogflowCXAgentDescription(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDialogflowCXAgentAvatarUri(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDialogflowCXAgentSpeechToTextSettings(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["enable_speech_adaptation"] = + flattenDialogflowCXAgentSpeechToTextSettingsEnableSpeechAdaptation(original["enableSpeechAdaptation"], d, config) + return []interface{}{transformed} +} +func flattenDialogflowCXAgentSpeechToTextSettingsEnableSpeechAdaptation(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDialogflowCXAgentStartFlow(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDialogflowCXAgentSecuritySettings(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDialogflowCXAgentEnableStackdriverLogging(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDialogflowCXAgentEnableSpellCorrection(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func expandDialogflowCXAgentDisplayName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDialogflowCXAgentDefaultLanguageCode(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDialogflowCXAgentSupportedLanguageCodes(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDialogflowCXAgentTimeZone(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDialogflowCXAgentDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDialogflowCXAgentAvatarUri(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDialogflowCXAgentSpeechToTextSettings(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedEnableSpeechAdaptation, err := expandDialogflowCXAgentSpeechToTextSettingsEnableSpeechAdaptation(original["enable_speech_adaptation"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnableSpeechAdaptation); val.IsValid() && !isEmptyValue(val) { + transformed["enableSpeechAdaptation"] = transformedEnableSpeechAdaptation + } + + return transformed, nil +} + +func expandDialogflowCXAgentSpeechToTextSettingsEnableSpeechAdaptation(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDialogflowCXAgentSecuritySettings(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDialogflowCXAgentEnableStackdriverLogging(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDialogflowCXAgentEnableSpellCorrection(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} diff --git a/google-beta/resource_dialogflow_cx_agent_generated_test.go b/google-beta/resource_dialogflow_cx_agent_generated_test.go new file mode 100644 index 0000000000..4bbf0337f2 --- /dev/null +++ b/google-beta/resource_dialogflow_cx_agent_generated_test.go @@ -0,0 +1,101 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccDialogflowCXAgent_dialogflowcxAgentFullExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDialogflowCXAgentDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDialogflowCXAgent_dialogflowcxAgentFullExample(context), + }, + { + ResourceName: "google_dialogflow_cx_agent.full_agent", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location"}, + }, + }, + }) +} + +func testAccDialogflowCXAgent_dialogflowcxAgentFullExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_dialogflow_cx_agent" "full_agent" { + display_name = "tf-test-dialogflowcx-agent%{random_suffix}" + location = "global" + default_language_code = "en" + supported_language_codes = ["fr","de","es"] + time_zone = "America/New_York" + description = "Example description." + avatar_uri = "https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png" + enable_stackdriver_logging = true + enable_spell_correction = true + speech_to_text_settings { + enable_speech_adaptation = true + } +} +`, context) +} + +func testAccCheckDialogflowCXAgentDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_dialogflow_cx_agent" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := googleProviderConfig(t) + + url, err := replaceVarsForTest(config, rs, "{{DialogflowCXBasePath}}projects/{{project}}/locations/{{location}}/agents/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = sendRequest(config, "GET", billingProject, url, config.userAgent, nil) + if err == nil { + return fmt.Errorf("DialogflowCXAgent still exists at %s", url) + } + } + + return nil + } +} diff --git a/google-beta/resource_dialogflowcx_agent_test.go b/google-beta/resource_dialogflowcx_agent_test.go new file mode 100644 index 0000000000..6462591074 --- /dev/null +++ b/google-beta/resource_dialogflowcx_agent_test.go @@ -0,0 +1,93 @@ +package google + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccDialogflowCXAgent_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": getTestOrgFromEnv(t), + "billing_account": getTestBillingAccountFromEnv(t), + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDialogflowCXAgent_basic(context), + }, + { + ResourceName: "google_dialogflow_cx_agent.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccDialogflowCXAgent_full(context), + }, + { + ResourceName: "google_dialogflow_cx_agent.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccDialogflowCXAgent_basic(context map[string]interface{}) string { + return Nprintf(` + resource "google_service_account" "dialogflowcx_service_account" { + account_id = "tf-test-dialogflow-%{random_suffix}" + } + + resource "google_project_iam_member" "agent_create" { + role = "roles/dialogflow.admin" + member = "serviceAccount:${google_service_account.dialogflowcx_service_account.email}" + } + + resource "google_dialogflow_cx_agent" "foobar" { + display_name = "tf-test-%{random_suffix}" + location = "global" + default_language_code = "en" + supported_language_codes = ["fr","de","es"] + time_zone = "America/New_York" + description = "Description 1." + avatar_uri = "https://storage.cloud.google.com/dialogflow-test-host-image/cloud-logo.png" + depends_on = [google_project_iam_member.agent_create] + } + `, context) +} + +func testAccDialogflowCXAgent_full(context map[string]interface{}) string { + return Nprintf(` + resource "google_service_account" "dialogflowcx_service_account" { + account_id = "tf-test-dialogflow-%{random_suffix}" + } + + resource "google_project_iam_member" "agent_create" { + role = "roles/dialogflow.admin" + member = "serviceAccount:${google_service_account.dialogflowcx_service_account.email}" + } + + resource "google_dialogflow_cx_agent" "foobar" { + display_name = "tf-test-%{random_suffix}update" + location = "global" + default_language_code = "en" + supported_language_codes = ["no"] + time_zone = "Europe/London" + description = "Description 2!" + avatar_uri = "https://storage.cloud.google.com/dialogflow-test-host-image/cloud-logo-2.png" + enable_stackdriver_logging = true + enable_spell_correction = true + speech_to_text_settings { + enable_speech_adaptation = true + } + depends_on = [google_project_iam_member.agent_create] + } + `, context) +} diff --git a/website/docs/r/dialogflow_cx_agent.html.markdown b/website/docs/r/dialogflow_cx_agent.html.markdown new file mode 100644 index 0000000000..3fc4883904 --- /dev/null +++ b/website/docs/r/dialogflow_cx_agent.html.markdown @@ -0,0 +1,163 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- +subcategory: "Dialogflow CX" +layout: "google" +page_title: "Google: google_dialogflow_cx_agent" +sidebar_current: "docs-google-dialogflow-cx-agent" +description: |- + Agents are best described as Natural Language Understanding (NLU) modules that transform user requests into actionable data. +--- + +# google\_dialogflow\_cx\_agent + +Agents are best described as Natural Language Understanding (NLU) modules that transform user requests into actionable data. You can include agents in your app, product, or service to determine user intent and respond to the user in a natural way. + + +To get more information about Agent, see: + +* [API documentation](https://cloud.google.com/dialogflow/cx/docs/reference/rest/v3/projects.locations.agents) +* How-to Guides + * [Official Documentation](https://cloud.google.com/dialogflow/cx/docs) + + +## Example Usage - Dialogflowcx Agent Full + + +```hcl +resource "google_dialogflow_cx_agent" "full_agent" { + display_name = "dialogflowcx-agent" + location = "global" + default_language_code = "en" + supported_language_codes = ["fr","de","es"] + time_zone = "America/New_York" + description = "Example description." + avatar_uri = "https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png" + enable_stackdriver_logging = true + enable_spell_correction = true + speech_to_text_settings { + enable_speech_adaptation = true + } +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `location` - + (Required) + The name of the location this agent is located in. + ~> **Note:** The first time you are deploying an Agent in your project you must configure location settings. + This is a one time step but at the moment you can only [configure location settings](https://cloud.google.com/dialogflow/cx/docs/concept/region#location-settings) via the Dialogflow CX console. + Another options is to use global location so you don't need to manually configure location settings. + +* `display_name` - + (Required) + The human-readable name of the agent, unique within the location. + +* `default_language_code` - + (Required) + The default language of the agent as a language tag. [See Language Support](https://cloud.google.com/dialogflow/cx/docs/reference/language) + for a list of the currently supported language codes. This field cannot be updated after creation. + +* `time_zone` - + (Required) + The time zone of this agent from the [time zone database](https://www.iana.org/time-zones), e.g., America/New_York, + Europe/Paris. + + +- - - + + +* `supported_language_codes` - + (Optional) + The list of all languages supported by this agent (except for the default_language_code). + +* `description` - + (Optional) + The description of this agent. The maximum length is 500 characters. If exceeded, the request is rejected. + +* `avatar_uri` - + (Optional) + The URI of the agent's avatar. Avatars are used throughout the Dialogflow console and in the self-hosted Web Demo integration. + +* `speech_to_text_settings` - + (Optional) + Settings related to speech recognition. + Structure is documented below. + +* `security_settings` - + (Optional) + Name of the SecuritySettings reference for the agent. Format: projects//locations//securitySettings/. + +* `enable_stackdriver_logging` - + (Optional) + Determines whether this agent should log conversation queries. + +* `enable_spell_correction` - + (Optional) + Indicates if automatic spell correction is enabled in detect intent requests. + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +The `speech_to_text_settings` block supports: + +* `enable_speech_adaptation` - + (Optional) + Whether to use speech adaptation for speech recognition. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/locations/{{location}}/agents/{{name}}` + +* `name` - + The unique identifier of the agent. + +* `start_flow` - + Name of the start flow in this agent. A start flow will be automatically created when the agent is created, and can only be deleted by deleting the agent. Format: projects//locations//agents//flows/. + + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 40 minutes. +- `update` - Default is 40 minutes. +- `delete` - Default is 4 minutes. + +## Import + + +Agent can be imported using any of these accepted formats: + +``` +$ terraform import google_dialogflow_cx_agent.default projects/{{project}}/locations/{{location}}/agents/{{name}} +$ terraform import google_dialogflow_cx_agent.default {{project}}/{{location}}/{{name}} +$ terraform import google_dialogflow_cx_agent.default {{location}}/{{name}} +``` + +## User Project Overrides + +This resource supports [User Project Overrides](https://www.terraform.io/docs/providers/google/guides/provider_reference.html#user_project_override). diff --git a/website/google.erb b/website/google.erb index 0454913bc5..92be8f9a55 100644 --- a/website/google.erb +++ b/website/google.erb @@ -2249,6 +2249,22 @@ +
  • + Dialogflow CX + +
  • +
  • Essential Contacts