diff --git a/bigip/resource_bigip_as3.go b/bigip/resource_bigip_as3.go index a5060572..e32bb0e2 100644 --- a/bigip/resource_bigip_as3.go +++ b/bigip/resource_bigip_as3.go @@ -144,11 +144,13 @@ func resourceBigipAs3() *schema.Resource { "tenant_name": { Type: schema.TypeString, Optional: true, + Computed: true, Description: "Name of Tenant. This name is used only in the case of Per-Application Deployment. If it is not provided, then a random name would be generated.", }, "tenant_filter": { Type: schema.TypeString, Optional: true, + Computed: true, Description: "Name of Tenant", }, "tenant_list": { @@ -220,7 +222,7 @@ func resourceBigipAs3Create(ctx context.Context, d *schema.ResourceData, meta in _ = d.Set("application_list", applicationList) _ = d.Set("per_app_mode", true) } else { - log.Printf("[INFO] Creating As3 config traditionally for tenants:%+v", tenantList) + log.Printf("[INFO] Creating AS3 config traditionally for tenants:%+v", tenantList) tenantCount := strings.Split(tenantList, ",") if tenantFilter != "" { log.Printf("[DEBUG] tenantFilter:%+v", tenantFilter) @@ -286,12 +288,13 @@ func resourceBigipAs3Create(ctx context.Context, d *schema.ResourceData, meta in } func resourceBigipAs3Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*bigip.BigIP) - log.Printf("[INFO] Reading As3 config") + log.Printf("[INFO] Reading AS3 config") var name string var tList string as3Json := d.Get("as3_json").(string) + perappMode := d.Get("per_app_mode").(bool) log.Printf("[INFO] AS3 config:%+v", as3Json) - if d.Get("as3_json") != nil { + if d.Get("as3_json") != nil && !perappMode { tList, _, _ = client.GetTenantList(as3Json) if createdTenants != "" && createdTenants != tList { tList = createdTenants diff --git a/docs/resources/bigip_as3.md b/docs/resources/bigip_as3.md index c95d8aea..b1ac8731 100644 --- a/docs/resources/bigip_as3.md +++ b/docs/resources/bigip_as3.md @@ -10,13 +10,19 @@ description: |- `bigip_as3` provides details about bigip as3 resource -This resource is helpful to configure as3 declarative JSON on BIG-IP. +This resource is helpful to configure AS3 declarative JSON on BIG-IP. + +~> This Resource also supports **Per-Application** mode of AS3 deployment, more information on **Per-Application** mode can be found [Per-App](https://clouddocs.f5.com/products/extensions/f5-appsvcs-extension/latest/userguide/per-app-declarations.html) + +-> For Supporting AS3 Per-App mode of deployment, AS3 version on BIG-IP should be > **v3.50** + +~> For Deploying AS3 JSON in Per-App mode, this resource provided with a attribute [tenant_name](#tenant_name) to be passed to add application on specified tenant, else random tenant name will be generated. + ## Example Usage ```hcl - # Example Usage for json file resource "bigip_as3" "as3-example1" { as3_json = file("example1.json") @@ -27,17 +33,40 @@ resource "bigip_as3" "as3-example1" { as3_json = file("example2.json") tenant_filter = "Sample_03" } +``` +## Example Usage for Per-App mode deployment +[perApplication as3](#perApplication_example) + +```hcl + +# Per-Application Deployment - Example Usage for json file with tenant name +resource "bigip_as3" "as3-example1" { + as3_json = file("perApplication_example.json") + tenant_name = "Test" +} + +# Per-Application Deployment - Example Usage for json file without tenant name - Random tenant name is generated in this case +resource "bigip_as3" "as3-example1" { + as3_json = file("perApplication_example.json") +} ``` ## Argument Reference - * `as3_json` - (Required) Path/Filename of Declarative AS3 JSON which is a json file used with builtin ```file``` function * `tenant_filter` - (Optional) If there are multiple tenants on a BIG-IP, this attribute helps the user to set a particular tenant to which he want to reflect the changes. Other tenants will neither be created nor be modified. +* `tenant_name` - (Optional) Name of Tenant. This name is used only in the case of Per-Application Deployment. If it is not provided, then a random name would be generated. + +* `per_app_mode` - (Computed) - Will specify whether is deployment is done via Per-Application Way or Traditional Way + +* `tenant_list` - (Optional) - List of tenants currently deployed on the Big-Ip + +* `application_list` - (Optional) - List of applications currently deployed on the Big-Ip + * `ignore_metadata` - (Optional) Set True if you want to ignore metadata changes during update. By default it is set to false * `as3_example1.json` - Example AS3 Declarative JSON file with single tenant @@ -167,6 +196,58 @@ resource "bigip_as3" "as3-example1" { ``` +* `perApplication_example` - Per Application Example - JSON file with multiple Applications (and no Tenant Details) + +```json +{ + "schemaVersion": "3.50.1", + "Application1": { + "class": "Application", + "service": { + "class": "Service_HTTP", + "virtualAddresses": [ + "192.1.1.1" + ], + "pool": "pool" + }, + "pool": { + "class": "Pool", + "members": [ + { + "servicePort": 80, + "serverAddresses": [ + "192.0.1.10", + "192.0.1.20" + ] + } + ] + } + }, + "Application2": { + "class": "Application", + "service": { + "class": "Service_HTTP", + "virtualAddresses": [ + "192.1.2.1" + ], + "pool": "pool" + }, + "pool": { + "class": "Pool", + "members": [ + { + "servicePort": 80, + "serverAddresses": [ + "192.0.2.10", + "192.0.2.20" + ] + } + ] + } + } +} +``` + ## Import As3 resources can be imported using the partition name, e.g., ( use comma separated partition names if there are multiple partitions in as3 deployments ) @@ -364,5 +445,4 @@ resource "bigip_as3" "test" { ``` -* `AS3 documentation` - https://clouddocs.f5.com/products/extensions/f5-appsvcs-extension/latest/userguide/composing-a-declaration.html - +* `AS3 documentation` - https://clouddocs.f5.com/products/extensions/f5-appsvcs-extension/latest/userguide/composing-a-declaration.html \ No newline at end of file diff --git a/vendor/github.com/f5devcentral/go-bigip/as3bigip.go b/vendor/github.com/f5devcentral/go-bigip/as3bigip.go index 8f803ea5..1016b39d 100644 --- a/vendor/github.com/f5devcentral/go-bigip/as3bigip.go +++ b/vendor/github.com/f5devcentral/go-bigip/as3bigip.go @@ -555,15 +555,29 @@ func (b *BigIP) AddTeemAgent(body interface{}) (string, error) { } func (b *BigIP) CheckSetting() (bool, error) { - - err, setting := b.getSetting(uriMgmt, uriShared, uriAppsvcs, uriSetting) + err, resp := b.getSetting(uriMgmt, uriShared, uriAppsvcs, uriSetting) if err != nil { return false, err } - log.Printf("[INFO] BigIP Setting:%+v", setting) - perAppDeploymentAllowed := setting.BetaOptions.PerAppDeploymentAllowed - + respRef := make(map[string]interface{}) + json.Unmarshal(resp, &respRef) + perAppDeploymentAllowed := false + if value, ok := respRef["betaOptions"].(map[string]interface{}); ok { //for AS3 version < 3.5 + perAppDeploymentAllowed = value["perAppDeploymentAllowed"].(bool) + } else if value, ok := respRef["perAppDeploymentAllowed"]; ok { // for As3 version 3.5 + perAppDeploymentAllowed = value.(bool) + } + log.Printf("[INFO] BigIP Setting perAppDeploymentAllowed:%+v", perAppDeploymentAllowed) return perAppDeploymentAllowed, nil + + // err, setting := b.getSetting(uriMgmt, uriShared, uriAppsvcs, uriSetting) + // if err != nil { + // return false, err + // } + // log.Printf("[INFO] BigIP Setting:%+v", setting) + // perAppDeploymentAllowed := setting.BetaOptions.PerAppDeploymentAllowed + + // return perAppDeploymentAllowed, nil } func (b *BigIP) AddServiceDiscoveryNodes(taskid string, config []interface{}) error { diff --git a/vendor/github.com/f5devcentral/go-bigip/bigip.go b/vendor/github.com/f5devcentral/go-bigip/bigip.go index 22592ccb..b87183ea 100644 --- a/vendor/github.com/f5devcentral/go-bigip/bigip.go +++ b/vendor/github.com/f5devcentral/go-bigip/bigip.go @@ -578,7 +578,7 @@ func (b *BigIP) Upload(r io.Reader, size int64, path ...string) (*Upload, error) } } -func (b *BigIP) getSetting(path ...string) (error, *BigIPSetting) { +func (b *BigIP) getSetting(path ...string) (error, []byte) { req := &APIRequest{ Method: "get", URL: b.iControlPath(path), @@ -586,22 +586,24 @@ func (b *BigIP) getSetting(path ...string) (error, *BigIPSetting) { } resp, err := b.APICall(req) - if err != nil { - var reqError RequestError - json.Unmarshal(resp, &reqError) - if reqError.Code == 404 { - return err, nil - } - return err, nil - } - - var setting BigIPSetting - err = json.Unmarshal(resp, &setting) - if err != nil { - return err, nil - } - - return nil, &setting + return err, resp + + // if err != nil { + // var reqError RequestError + // json.Unmarshal(resp, &reqError) + // if reqError.Code == 404 { + // return err, nil + // } + // return err, nil + // } + + // var setting BigIPSetting + // err = json.Unmarshal(resp, &setting) + // if err != nil { + // return err, nil + // } + + // return nil, &setting } // Get a urlString and populate an entity. If the entity does not exist (404) then the