Giter VIP home page Giter VIP logo

citrix / terraform-provider-citrixadc Goto Github PK

View Code? Open in Web Editor NEW
113.0 15.0 57.0 55.49 MB

Part of NetScaler Automation Toolkit | https://github.com/netscaler/automation-toolkit

Home Page: https://registry.terraform.io/providers/citrix/citrixadc

License: Apache License 2.0

Makefile 0.04% Go 99.95% Shell 0.02%
citrix-netscaler nitro-api terraform-provider terraform devops cloud citrix-adc load-balancer vpx netscaler

terraform-provider-citrixadc's Introduction

Terraform Citrix ADC Provider

Citrix has developed a custom Terraform provider for automating Citrix ADC deployments and configurations. Using Terraform, you can custom configure your ADCs for different use-cases such as Load Balancing, SSL, Content Switching, GSLB, WAF etc.

Learn more about Citrix ADC Automation here

πŸ“For deploying Citrix ADC in Public Cloud - AWS and Azure, check out cloud scripts in github repo terraform-cloud-scripts.

βœ‰οΈ For any immediate issues or help , reach out to us at [email protected] !

Examples and Modules

Terrraform Provider Documentation

  1. Why Terraform for Citrix ADC ?
  2. Navigating Repository
  3. Understanding Provider Configuration
  4. Understanding Resource Configuration
  5. General guidelines on ADC configurations
  6. Commiting changes to Citrix ADC's persistent store
  7. List of ADC use-cases supported through Terraform
  8. Using remote-exec for one-time tasks

Beginners Guide to Automating ADC with Terraform

  1. Hands-on lab with ADC automation with Terraform
  2. Install Terraform in your own setup
  3. Understanding the ADC terraform provider repository)
  4. Get your first terraform config into ADC
  5. How to write terraform resources file for ADC
  6. Set up SSL-Offloading use-case in ADC
  7. Committing changes to Citrix ADC's persistent store
  8. Managing ADC configs drifts in terraform
  9. Importing ADC configs into Terraform resources file

Advanced guide on Automating ADC with Terraform

  1. Deploy ADC in AWS using Terraform
  2. Leveraging Terraform workspaces to manage multiple ADCs
  3. Dynamically updates Services using Consul-Terraform-Sync
  4. Blue-Green Deployment with Citrix ADC and Azure Pipelines

Why Terraform for Citrix ADC ?

Terraform is an open-source infrastructure as code software tool that provides a consistent CLI workflow to manage hundreds of cloud services.Terraform codifies cloud APIs into declarative configuration files. Terraform can be used to deploy and configure ADC. Configuring Citrix ADC through Terraform provides multiple benefits.

  1. Infrastucture as Code approach to ADC -You can store the ADC configs in scm tools like GitHub and version and track it like just other code repositories you have.
  2. Declarative Approach to ADC automation - Users just need to defined the target state of ADC. ADC terraform resources will make the appropriate API calls to achieve the target state.
  3. ADC resources files in Terraform are human friendly and easy to understand.
  4. Abstract away the complexity associated with Citrix ADC internals architecture.
  5. Detect the configuration drifts on ADC through Terraform easily.

Navigating the repository

  1. citrixadc folder - Contains all the ADC resources library that we support through Terraform. These resource libraries will internally call NITRO APIS to configure target ADC.
  2. examples folder - Contain the examples for users to use various ADC resources e.g simple_lb folder contains the resources.tf that illustrates how citrixadc_lbvserver resource can be used to create a Load Balancing vserver on target ADC. Similarly , different folders contains examples on defining different resources. Users are expected to review these examples and define their desired ADC configurations.
  3. docs folder` - https://github.com/citrix/terraform-provider-citrixadc/tree/master/docs/resources - contains the documentation of all resources confgirations supported through Terraform. Refer this to understand the different arguments, values that a particular resource takes.

Understanding Provider Configuration

provider.tf contains the information on target ADC where you want to apply configuration.

provider "citrixadc" {
    username = "${var.ns_user}"  # You can optionally use `NS_LOGIN` environment variables.
    password = "${var.ns_password}"  # You can optionally use `NS_PASSWORD` environment variables.
    endpoint = "http://10.71.136.250/"  # You can optionally use `NS_URL` environment variables.
}

We can use a https URL and accept the untrusted authority certificate on the Citrix ADC by specifying insecure_skip_verify = true

To use https without the need to set insecure_skip_verify = true follow this guide on how to replace the default TLS certificate with one from a trusted Certifcate Authority.

Use of https is preferred. Using http will result in all provider configuration variables as well as resource variables to be transmitted in cleartext. Anyone observing the HTTP data stream will be able to parse sensitive values such as the provider password.

Avoid storing provider credentials in the local state by using a backend that supports encryption. The hasicorp vault provider is also recommended for storing sensitive data.

You can also use environment variables as stated in the comments above.

The following arguments are supported.

  • username - This is the user name to access to Citrix ADC. Defaults to nsroot unless environment variable NS_LOGIN has been set
  • password - This is the password to access to Citrix ADC. Defaults to nsroot unless environment variable NS_PASSWORD has been set
  • endpoint - (Required) Nitro API endpoint in the form http://<NS_IP>/ or http://<NS_IP>:<PORT>/. Can be specified in environment variable NS_URL
  • insecure_skip_verify - (Optional, true/false) Whether to accept the untrusted certificate on the Citrix ADC when the Citrix ADC endpoint is https
  • proxied_ns - (Optional, NSIP) The target Citrix ADC NSIP for MAS proxied calls. When this option is defined, username, password and endpoint must refer to the MAS proxy.

The username, password and endpoint can be provided in environment variables NS_LOGIN, NS_PASSWORD and NS_URL.

Resource Configuration

Resources.tf contains the desired state of the resources that you want on target ADC. E.g. For creating a Load Balancing vserver in ADC following resource.tf contains the desired configs of lbvserver

citrixadc_lbvserver

resource "citrixadc_lbvserver" "foo" {
  name = "sample_lb"
  ipv46 = "10.71.136.150"
  port = 443
  servicetype = "SSL"
  lbmethod = "ROUNDROBIN"
  persistencetype = "COOKIEINSERT"
  sslcertkey = "${citrixadc_sslcertkey.foo.certkey}"
  sslprofile = "ns_default_ssl_profile_secure_frontend"
}

In order to understand the arguments, possible values, and other arguments available for a given resource, refer the NITRO API documentation https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/load-balancing/lbvserver/lbvserver/ and the Terraform documentation such as https://github.com/citrix/terraform-provider-citrixadc/blob/master/docs/resources/lbvserver.md .

the attribute state is not synced with the remote object. If the state of the lb vserver is out of sync with the terraform configuration you will need to manually taint the resource and apply the configuration again.

General guidelines on configuring ADC

The subfolders in the example folder contains examples of different ADC configurations through terraform. Refer to simple_lb example to understand below structure and usage.

Structure
  • resources.tf describes the actual NetScaler config objects to be created. The attributes of these resources are either hard coded or looked up from input variables in terraform.tfvars
  • variables.tf describes the input variables to the terraform config. These can have defaults
  • provider.tf is used to specify the username, password and endpoint of the NetScaler. Alternatively, you can set the NS_URL, NS_LOGIN and NS_PASSWORD environment variables.
  • terraform.tfvars has the variable inputs specified in variables.tf

Using

  • Modify the terraform.tfvars and provider.tf to suit your own NetScaler deployment.
  • Use terraform plan and terraform apply to configure the NetScaler.

Updating your configuration

Modify the set of backend services and use terraform plan and terraform apply to verify the changes

Commiting changes to Citrix ADC's persistent store

The provider will not commit the config changes to Citrix ADC's persistent store. To do this, run the shell script ns_commit.sh:

export NS_URL=http://<host>:<port>/
export NS_LOGIN=nsroot
export NS_PASSWORD=nsroot
./ns_commit.sh

To ensure that the config is saved on every run, we can use something like terraform apply && ns_commit.sh

ADC Use-Case supported through Terraform

List of Use-Cases supported in ADC can be found in here https://registry.terraform.io/providers/citrix/citrixadc/latest/docs .

Using remote-exec for one-time tasks

Terraform is useful for maintaining desired state for a set of resources. It is less useful for tasks such as network configuration which don't change. Network configuration is like using a provisioner inside Terraform. The directory examples/remote-exec show examples of how Terraform can use ssh to accomplish these one-time tasks.


Beginners Guide to ADC Automation with Terraform

Hands-on lab with ADC automation with Terraform

Try out our Hands on Lab to experience whats it like using Terraform for ADC.

Install Terraform in your own setup

First step to using Terraform for ADC is to install Terraform CLI. Refer the Hashicorp documentation for installing Terraform CLI for your own environment.

Understanding the ADC terraform provider repository

Refer the Navigating our repository section

Get your first terraform config into ADC

Follow the article on Getting started with Terraform on NetScaler to get your first configuration

How to write terraform resources file for ADC

To write the Terraform resources for Citrix ADC, refer the following links NITRO API documentation or terraform registry documentation.

Set up SSL-Offloading use-case in ADC

Here is the Terraform Templatethat you follow to configure SSL Offloading.

Committing changes to Citrix ADC's persistent store

Refer the commiting changes section

Managing ADC configs drifts in terraform

You want to see the current state of ADC entities in Terraform

  • Use terraform refresh to update your local terraform state file to match with existing ADC state
  • Use terraform show to show the current state for your entire configuration
  • Use terraform state list to show the resources that are being tracked/managed via Terraform
  • To inspect a particular entity use terraform state show <entity_name> e.g. terraform state show citrixadc_servicegroup.tf_servicegroup

If you want to override the ADC configuration with the configs you have in Terraform resource file then

  • You can run terraform plan to see the drifts/diff between the two state
  • Run terraform apply to push the desired configs( in your Terraform resource file) to your ADC.

Update your terraform state file to reflect the current/true state of ADC

  • Use terraform refresh to update your local terraform state file to match with existing ADC state

Importing ADC configs into Terraform resources file

Learn how to import existing NetScaler configurations into Terraform resources here


Advanced guide on Automating ADC with Terraform

Deploy ADC in AWS using Terraform

Refer our terraform cloud scripts for AWS and demo video

Leveraging Terraform workspaces to manage multiple ADCs

TBD

Dynamically updates Services using Consul-Terraform-Sync

Our Consul-Terraform-Sync integration allows users to automatically create, update and delete Service groups in Citrix ADC that are synced with the Consul Terraform Sync framework.

Blue-Green Deployment with Citrix ADC and Azure Pipelines

Integrate ADC and configure it faciliate Blue-Green deployment using Terraform.Check out the solution

terraform-provider-citrixadc's People

Contributors

chiradeep avatar chrism3rsi avatar dependabot[bot] avatar fungusakafungus avatar jen20 avatar olljanat avatar ravager-dk avatar rohit-myali avatar sean- avatar sumanth-lingappa avatar vadharm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

terraform-provider-citrixadc's Issues

CitrixADC provider - Supplied URL does not have a HTTP/HTTPS scheme error

Describe the bug
I receive the following error when I'm doing a terraform plan command.

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

Error: Supplied URL does not have a HTTP/HTTPS scheme

on provider.tf line 3, in provider "citrixadc":
3: provider "citrixadc" {

This is the content of my provider.tf file:

provider "citrixadc" {
username = var.admin_username
password = var.admin_password
endpoint = "http://${azurerm_public_ip.mgmtpip.ip_address}"
}

However, azurerm_public_ip.mgmtpip.ip_address is obviously not set yet until the netscaler is created.

I would like to be able to set the endpoint URL to be set as dynamic later down the stage rather than setting it up as static url at the beginning.

Is it possible to do this?

Environment (please complete the following information):

  • OS: Ubuntu
  • Terraform version v0.12.21

How to bind csvserver and lbvserver

I want to bind a csvserver and a lbvserver, but there is no csvserver_lbvserver_binding resource...

bind cs vserver sample_cs -lbvserver sample_lb

or (as I would expect it):

resource "netscaler_csvserver_lbvserver_binding" "sample_cs_sample_lb" {
  csvserver = "${netscaler_csvserver.foo.name}"
  lbvserver = "${netscaler_lbvserver.foo.name}"
}

Add CI build

Now when we have contributing guidelines here then next logical step would be include CI build which will run for all PRs.

IMO, CircleCI + Netscaler CPX combination is interesting option to that one. I can investigate it.

Response Code Field Missing from Resource netscaler_lbmonitor

The definition for netscaler_lbmonitor resource is missing the respcode field.

From the Nitro API docs:
respcode | <String[]> | Read-write | Response codes for which to mark the service as UP. For any other response code, the action performed depends on the monitor type. HTTP monitors and RADIUS monitors mark the service as DOWN, while HTTP-INLINE monitors perform the action indicated by the Action parameter.

Terraform resource example:

resource "netscaler_lbmonitor" "https_ignore_errors" {
monitorname = "https_ignore_errors"
type = "HTTP"
secure = "YES"
interval = 5
resptimeout = 3
respcode = ["200","301-302","400-404","500-504"]
}

Output of terraform plan:

Error: netscaler_lbmonitor.https_ignore_errors: : invalid or unknown key: respcode

TF Acceptance Testing Fails with ServiceGroups

using version v0.8.2

TF_ACC=1 go test -v
=== RUN   TestProvider
--- PASS: TestProvider (0.00s)
=== RUN   TestProvider_impl
--- PASS: TestProvider_impl (0.00s)
=== RUN   TestAccCspolicy_basic
--- PASS: TestAccCspolicy_basic (3.27s)
=== RUN   TestAccCsvserver_basic
--- PASS: TestAccCsvserver_basic (1.52s)
=== RUN   TestAccLbmonitor_basic
--- PASS: TestAccLbmonitor_basic (1.20s)
=== RUN   TestAccLbvserver_basic
--- PASS: TestAccLbvserver_basic (1.51s)
=== RUN   TestAccService_basic
--- PASS: TestAccService_basic (3.20s)
=== RUN   TestAccServicegroup_basic
--- FAIL: TestAccServicegroup_basic (3.11s)
	testing.go:268: Step 0 error: After applying this step, the plan was not empty:
		
		DIFF:
		
		UPDATE: netscaler_servicegroup.foo
		  servicegroupmembers.1629640711: "" => "172.20.0.9:80"
		  servicegroupmembers.1682487865: "172.20.0.11:8080:1" => ""
		  servicegroupmembers.2927490466: "" => "172.20.0.11:8080"
		  servicegroupmembers.4266564889: "" => "172.20.0.10:80"
		  servicegroupmembers.526377631:  "172.20.0.9:80:1" => ""
		  servicegroupmembers.537949203:  "172.20.0.10:80:1" => ""
		
		STATE:
[...]
		  servicegroupmembers.# = 3
		  servicegroupmembers.1682487865 = 172.20.0.11:8080:1
		  servicegroupmembers.526377631 = 172.20.0.9:80:1
		  servicegroupmembers.537949203 = 172.20.0.10:80:1
[...]
FAIL
exit status 1
FAIL	terraform-provider-netscaler	13.992s

I can make the error go away if I modify resource_servicegroup_test.go
[BEFORE]

servicegroupmembers = ["172.20.0.9:80", "172.20.0.10:80", "172.20.0.11:8080"]

[AFTER]

servicegroupmembers = ["172.20.0.9:80:1", "172.20.0.10:80:1", "172.20.0.11:8080:1"]

I think what is happening is that the config has "[ip]:[port]" set but the plugin during createServicegroupFunc is appending [weight] making it [ip]:[port]:[weight] to the state.

Windows Build

Please update the Makefile to Build and Release Windows binaries.

RFE - Bind existing policies to virtual servers

It is currently not possible to bind existing policies to cs/lbserver.

For example:
resource "citrixadc_responderpolicy" "rsp_redirect_binding_vserver" {
name = "RSP_REDIRECT"
lbvserverbinding {
name = citrixadc_lbvserver.redirect_vserver.name
bindpoint = "REQUEST"
priority = 100
}
}

This will fail if the responder policy RSP_REDIRECT already exists in the configuration.
The actual error will also indicate that you need to supply a rule for the policy, and an action.

Point is, we often have loads of policies which are being re-used on a system, so it makes no sense to create separate policies for each virtual server we wish to bind the policy to.

There should be a resource like citrixadc_responderpolicy_binding to bind an existing policy to an existing vserver.

This applies to:

  • responder
  • rewrite
  • content-switching

Could this be added to the terraform provider?

Thank you very much!

Terraform Provider Development Program - Initial review

I’ve taken a look at the provider here and would like to say great work so far! I do have feedback outlined below that I’d like to see addressed before we move on to the next steps. I’m opening this issues as a sort of checklist for tracking items and discussion. If it works better for you, this changes can be added to a separate branch if any changes conflict with your current build process. The review was done on the develop branch at git commit ba32e8b

  • Within the tools/ directory it looks like you have an addition provider build for Netscaler, is this code used by the provider? It not, it should be removed from the repository.

  • The provider should use Go Modules for the vending of required code dependancies, as well, all dependancies should be checked into the vendor directory, so that it can be built without fetching dependancies.

  • Since the provider is build and released from inside our TeamCIty server, there is a specific GNUmakefile that must be used, feel free to copy the GitHub provider makefile and will just have to update the variable on line 4 to PKG_NAME=PROVIDER_NAME

  • Scripts: There are a three bash scripts that are used in the provider build and release workflow, the GitHub provider has the current used scripts. Can you add the changelog-links.sh, gogetcookie.sh scripts and remove the errcheck.sh file.

  • One of our Terraform Ecosystem engineers built a linter to help align coding best practices for providers. You should use it along with your development. https://github.com/bflad/tfproviderlint

  • Each Terraform provider must have a CHANGELOG that is updated during reach release. Since the changeling is updated by a bot during the release it must be in a certain format. With the AWS provider changelog as an example, the version of the next release should be tagged as β€œ1.0.0 (Unreleased)” and will then be updated with a date by the release-bot.

  • I see you’ve had this repository under an Apache license, currently all official Terraform provider use a Mozilla Public License 2.0 within each repo, could you make this update to the repository?

  • There is a standard README.md for of the official provider, see Null provider README.md

  • The resource file naming convention is as follows, resource_providername_resource_name.go which means the file resource_cspolicy.go should be named resource_citrixadc_cspolicy.go and its corresponding acceptance test should be named resource_citrixadc_cspolicy_test.go , this should be follows across all resource files.

  • All providers in the terraform-providers/ GitHub org have a TravisCI check run on each PR that is opened. Can you please add a .travis.yaml file to make the standard configuration

  • There are a few files that won’t be needed once the provider is under the terraform-providers/ organization; .circleci, ISSUE_TEMPLATE, Gopkg.lock, Gopkg.toml, ns_commit.sh

Let me know if you have any questions, I look forward to releasing this provider with you'll!

Best,
Chris

If not present, Server not created when adding to service group with name

Hi,

I tried using the latest release of the provider (v0.11.9) but here is what I noticed:

  1. When I add server to the service group using IP, the provider is able to create a new server where the servername and ip are both the ip address.

  2. When I try to add server to the service group using servername, the provider does not create a new server and hence its not able to bind the server to the service group unless a server with that name already exists on the netscaler.

The functionality that I was looking for in my automation was the ability to create a server with a servername and to add it to my service group on creation of my VM.

The api call that is used in the creation of the resource is able to create a a new server resource when an IP address is given but not if a servername is used and thereby giving an
error = { "errorcode": 351, "message": "No such server", "severity": "ERROR" }

Are there some settings I am missing in my netscaler that are now allowing the provider to create a server by servername and then add it to the servicegroup?

Thanks

A continuation of Issue #26:

Add support for sslprofile settings

Failure when removing 'backend' server/service from list

Steps to reproduce :

resources.tf

resource "netscaler_lbmonitor" "lbmonitor" {
  monitorname = "mon_${var.ingress["name"]}"
  type = "${var.backends_config["service_type"]}"
  interval = 350
  resptimeout = 250
}

resource "netscaler_server" "backends" {
  count = "${length(var.backends)}"

  name = "srv_${format("%s_%s", var.ingress["name"], replace(var.backends[count.index], "/[:.]+/", ""))}"
  ipaddress = "${var.backends[count.index]}"
}

resource "netscaler_servicegroup" "backend" {
  servicegroupname = "sg_${var.ingress["name"]}"
  lbvservers = ["${netscaler_lbvserver.lbvserver.name}"]
  servicetype = "${var.backends_config["service_type"]}"
  servicegroupmembers_by_servername = ["${formatlist("%s:%s", netscaler_server.backends.*.name, var.backends_config["port"])}"]
}

resource "netscaler_lbvserver" "lbvserver" {
  name = "lbvs_${var.ingress["name"]}"
  ipv46 = "${var.ingress["ip"]}"
  port = "${var.ingress["port"]}"
  servicetype = "${var.ingress["service_type"]}"
  lbmethod = "ROUNDROBIN"
  persistencetype = "COOKIEINSERT"
}

variables.tf

variable "ns_user" {
  default = "nsroot"
}

variable "ns_password" {
  default = "nsroot"
}

variable "ns_hostname" {
  default = "ns.domain.tld"
}

variable "ingress" {
  type = "map"
  "description" = "name, vip, port and servicetype for the load balancer"
  default {
    port = 443
    service_type = "HTTP"
  }
}

variable "backends_config" {
  type = "map"
  "description" = "port and servicetype for the backend services"
  default {
    backend_port = 80
    service_type = "HTTP"
  }
}

variable "backends" {
  type = "list"
  description = "List of backend services [ipaddress:port]"
}

local.tfvars (first run: create everything)

ingress = {
  name = "ademoapp"
  service_type = "HTTP"
  ip = "10.42.42.100"
  port = 80
}

backends_config = {
  clttimeout = 40
  port = 80
  service_type = "HTTP"
}

backends = [
  "10.42.42.1",
  "10.42.42.2",
  "10.42.42.3",
]

Create the lbvserver and it's backends :

terraform plan -var-file=local.tfvars -out terraform.plan
terraform apply "terraform.plan"

Now change the backends list in local.tfvars to:

backends = [
  "10.42.42.1",
  "10.42.42.3",
]

and run terraform again:

terraform refresh -var-file=local.tfvars
terraform plan -var-file=local.tfvars -out terraform.plan
terraform apply "terraform.plan"

EXPECTED RESULT: 10.42.42.2 removed
ACTUAL RESULT:

first try:

terraform plan -var-file=local.tfvars -out terraform.plan
  ~ netscaler_server.backends[1]
      ipaddress:                                    "10.42.42.2" => "10.42.42.3"
      name:                                         "srv_ademoapp_1042422" => "srv_ademoapp_1042423"
  - netscaler_server.backends[2]
  ~ netscaler_servicegroup.backend
      servicegroupmembers_by_servername.#:          "3" => "2"
      servicegroupmembers_by_servername.1839026872: "srv_ademoapp_1042423:80:1" => ""
      servicegroupmembers_by_servername.213590207:  "" => "srv_ademoapp_1042423:80"
      servicegroupmembers_by_servername.2796742708: "" => "srv_ademoapp_1042421:80"
      servicegroupmembers_by_servername.2797699357: "srv_ademoapp_1042422:80:1" => ""
      servicegroupmembers_by_servername.542503859:  "srv_ademoapp_1042421:80:1" => ""
Plan: 0 to add, 2 to change, 1 to destroy.



terraform apply "terraform.plan"
netscaler_server.backends[2]: Destroying... (ID: srv_ademoapp_1042423)
netscaler_server.backends[1]: Modifying... (ID: srv_ademoapp_1042422)
  ipaddress: "10.42.42.2" => "10.42.42.3"
  name:      "srv_ademoapp_1042422" => "srv_ademoapp_1042423"
netscaler_server.backends[2]: Destruction complete after 0s
Error: Error applying plan:
1 error(s) occurred:
* netscaler_server.backends[1]: 1 error(s) occurred:
* netscaler_server.backends.1: Error updating server srv_ademoapp_1042423

idempotent right, so let's try again:

terraform plan -var-file=local.tfvars -out terraform.plan
  ~ netscaler_server.backends[1]
      ipaddress:                                    "10.42.42.2" => "10.42.42.3"
      name:                                         "srv_ademoapp_1042422" => "srv_ademoapp_1042423"
  ~ netscaler_servicegroup.backend
      servicegroupmembers_by_servername.213590207:  "" => "srv_ademoapp_1042423:80"
      servicegroupmembers_by_servername.2796742708: "" => "srv_ademoapp_1042421:80"
      servicegroupmembers_by_servername.2797699357: "srv_ademoapp_1042422:80:1" => ""
      servicegroupmembers_by_servername.542503859:  "srv_ademoapp_1042421:80:1" => ""
Plan: 0 to add, 2 to change, 0 to destroy.



terraform apply "terraform.plan"
netscaler_server.backends[1]: Modifying... (ID: srv_ademoapp_1042422)
  ipaddress: "10.42.42.2" => "10.42.42.3"
  name:      "srv_ademoapp_1042422" => "srv_ademoapp_1042423"
netscaler_server.backends[1]: Modifications complete after 0s (ID: srv_ademoapp_1042422)
Error: Error applying plan:
1 error(s) occurred:
* netscaler_servicegroup.backend: netscaler_servicegroup.backend: diffs didn't match during apply. This is a bug with Terraform and should be reported as a GitHub Issue.
Please include the following information in your report:
    Terraform Version: 0.11.11
    Resource ID: netscaler_servicegroup.backend
    Mismatch reason: attribute mismatch: servicegroupmembers_by_servername.213590207
    Diff One (usually from plan): *terraform.InstanceDiff{mu:sync.Mutex{state:0, sema:0x0}, Attributes:map[string]*terraform.ResourceAttrDiff{"servicegroupmembers_by_servername.542503859":*terraform.ResourceAttrDiff{Old:"srv_ademoapp_1042421:80:1", New:"", NewComputed:false, NewRemoved:true, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "servicegroupmembers_by_servername.213590207":*terraform.ResourceAttrDiff{Old:"", New:"srv_ademoapp_1042423:80", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "servicegroupmembers_by_servername.2796742708":*terraform.ResourceAttrDiff{Old:"", New:"srv_ademoapp_1042421:80", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "servicegroupmembers_by_servername.2797699357":*terraform.ResourceAttrDiff{Old:"srv_ademoapp_1042422:80:1", New:"", NewComputed:false, NewRemoved:true, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}}, Destroy:false, DestroyDeposed:false, DestroyTainted:false, Meta:map[string]interface {}(nil)}
    Diff Two (usually from apply): *terraform.InstanceDiff{mu:sync.Mutex{state:0, sema:0x0}, Attributes:map[string]*terraform.ResourceAttrDiff{"servicegroupmembers_by_servername.542503859":*terraform.ResourceAttrDiff{Old:"srv_ademoapp_1042421:80:1", New:"", NewComputed:false, NewRemoved:true, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "servicegroupmembers_by_servername.2796742708":*terraform.ResourceAttrDiff{Old:"", New:"srv_ademoapp_1042421:80", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "servicegroupmembers_by_servername.3020376026":*terraform.ResourceAttrDiff{Old:"", New:"srv_ademoapp_1042422:80", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "servicegroupmembers_by_servername.2797699357":*terraform.ResourceAttrDiff{Old:"srv_ademoapp_1042422:80:1", New:"", NewComputed:false, NewRemoved:true, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}}, Destroy:false, DestroyDeposed:false, DestroyTainted:false, Meta:map[string]interface {}(nil)}

Add call for "bind policy stringmap"

I want to be able to add entries to a stringmap on Citrix ADC from Terraform.

CLI Command:
bind policy stringmap <stringmap_name> <stringmap_key> <stringmap_value>

I believe in the Nitro API, it is called policystringmap_binding or policystringmappattern_binding.

Thanks!

Creation of citrixadc_servicegroup with 'nameserver' parameter fails.

Describe the bug

It looks a lot like the provider thinks that the 'nameserver' parameter of the citrixadc_servicegroup object 'belongs' to that object where it appears to actually belong to the binding of service to servicegroup. I've taken plenty of time to isolate it down to just the presence or absence of the 'nameserver' parameter.

So for example using the provider to replicate this documentation does not work:

https://docs.citrix.com/en-us/citrix-adc/current-release/dns/service-discovery-using-dns-srv-records.html

PS. Redacted this a lot because of obvious security sensitivities.

To Reproduce

TF code:

resource "citrixadc_servicegroup" "cloud_thing1_svcg" {
servicegroupname = "cloud_thing1_svcg"
servicetype = "HTTP"
autoscale = "DNS"
nameserver = "10.10.10.10"
depends_on = [
citrixadc_server.cloud_thing1_srv,
citrixadc_lbvserver.thing2-dns-udp-cloud
]
servicegroupmembers_by_servername = ["cloud_thing1_srv"]
lbvservers = [ citrixadc_lbvserver.thing1.name ]
}

terraform apply:

citrixadc_server.cloud_thing1_srv: Modifying... [id=cloud_thing1_srv]
citrixadc_server.cloud_thing1_srv: Modifications complete after 0s [id=cloud_thing1_srv]
citrixadc_servicegroup.cloud_thing1_svcg: Creating...

Error: [ERROR] go-nitro: Failed to create resource of type servicegroup, name=cloud_thing1_svcg, err=failed: 400 Bad Request ({ "errorcode": 1093, "message": "Argument pre-requisite missing [nameServer, serverName]", "severity": "ERROR" })

on backends_thing1.tf line 14, in resource "citrixadc_servicegroup" "cloud_thing1_svcg":
14: resource "citrixadc_servicegroup" "cloud_thing1_svcg" {

Comment out the nameserver parameter and things are created fine, but this doesn't meet our needs because being able to specify the nameserver is essential for our purposes.

Expected behavior

It should work and the nameserver be applied to the binding object not the servicegroup object.

I guess the 'nameserver' element needs removing and a servicegroup-to-server binding object added where it should go instead? It might be that the code is already trying to do this, in a non-obvious way.

Anyway, equivalent to doing this on the CLI:

bind servicegroup cloud_thing1_svcg cloud_thing1_srv -nameServer 10.10.10.10

But I can't see an existing object type in the provider to do that?

Logs

The logs don't seem to show anything other than the expected JSON being sent, including the 'nameserver' field when specified, which causes the error, the payload being:

'{"servicegroup": {"autoscale":"DNS","nameserver":"10.10.10.10","servicegroupname":"cloud_thing1_svcg","servicetype":"HTTP"}}'

If I send the same payload via curl I get the same error as terraform reports. I've ruled out case sensitivity being the issue.

Environment (please complete the following information):

  • OS: Linux
  • Provider version: 0.12.37 (and one or two earlier versions possibly).
  • Terraform version: 0.12.29
  • Citrix ADC version: NS12.1: Build 56.22.nc

Binding Service to multiple VirtualServers

Hi,

I saw a similar issue (#5 ) what already fixed.
Can you please implement the same for service?
Or for lbvserver resource change the servicename parameter from String to TypeSet?
Maybe both would be the perfect solution.

Thanks in advanced

Unable to add "add ns ip 10.10.1.5 255.255.255.0 -type vip" command via remote-exec

Describe the bug
I'm deploying Citrix ADC in Azure using Terraform on Azure CloudShell in a two-arm mode. I have two ip addresses on wan-subnet. First ip address is the vip and second ip address is the snip.
Part of my terraform config has a remote-exec components to ssh into the netscaler and run the following list of commands:

  • add ns ip 10.10.1.5 255.255.255.0 -type vip
  • add ns ip 10.10.2.4 255.255.255.0 -type snip
  • save config
    My terraform config successfully provisioned the Citrix ADC however it failed when it comes to remote-exec part.

Question:

  • How can I perform the following command on the ns cli?
  • Is there a citrixadc terraform module that is equivalent to perform the above commands?

The following error is displayed:

azurerm_virtual_machine.vm (remote-exec): Connecting to remote host via SSH...
azurerm_virtual_machine.vm (remote-exec):   Host: 52.147.4.242
azurerm_virtual_machine.vm (remote-exec):   User: nsroot
azurerm_virtual_machine.vm (remote-exec):   Password: true
azurerm_virtual_machine.vm (remote-exec):   Private key: false
azurerm_virtual_machine.vm (remote-exec):   Certificate: false
azurerm_virtual_machine.vm (remote-exec):   SSH Agent: false
azurerm_virtual_machine.vm (remote-exec):   Checking Host Key: false
azurerm_virtual_machine.vm (remote-exec): Connected!


Error: Failed to upload script: Error chmodding script file to 0777 in remote machine error executing "chmod 0777 /tmp/terraform_1432064364.sh": Process exited with status 1:
###############################################################################
#                     CallHome has been enabled by default.                   #
# This feature lets the NetScaler device/instance automatically upload        #
# diagnostic and usage information to Citrix. This data will help detect      #
# critical errors and will also be used to improve the features and the       #
# product.                                                                    #
#                                                                             #
# This feature can be configured anytime using the command line interface or  #
# the configuration utility. Please see the documentation for more details.   #
###############################################################################
 Done
ERROR: No such command
ERROR: No such command

Thanks in adv for your help.

To Reproduce
Please see my terraform configuration below.


# Define the variables and default values to be used throughout this script
variable "admin_username" {
  default = "nsroot"
}

variable "admin_password" {
  default = "S0m3Pa55w0rd!"
}

variable "resource_prefix" {
  default = "tfnsdemo"
}

# You'll usually want to set this to a region near you.
variable "location" {
  default = "australiaeast"
}



# Configure the provider.
provider "azurerm" {
  version = "~>1.31"
}

# Create a resource group
resource "azurerm_resource_group" "rg" {
  name     = "${var.resource_prefix}_rg"
  location = var.location
}

# Create virtual network and three subnets
resource "azurerm_virtual_network" "vnet" {
  name                = "${var.resource_prefix}-vnet"
  address_space       = ["10.10.0.0/16"]
  location            = var.location
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "wansubnet" {
  name                 = "wansubnet"
  resource_group_name  = "${azurerm_resource_group.rg.name}"
  virtual_network_name = "${azurerm_virtual_network.vnet.name}"
  address_prefix       = "10.10.1.0/24"
}

resource "azurerm_subnet" "lansubnet" {
  name                 = "lansubnet"
  resource_group_name  = "${azurerm_resource_group.rg.name}"
  virtual_network_name = "${azurerm_virtual_network.vnet.name}"
  address_prefix       = "10.10.2.0/24"
}


# Create public IP for management interface 
resource "azurerm_public_ip" "mgmtpip" {
  name                         = "${var.resource_prefix}-mgmtPIP"
  location                     = var.location
  resource_group_name          = azurerm_resource_group.rg.name
  allocation_method            = "Static"
}

# Create public IP for WAN interface 
resource "azurerm_public_ip" "wanpip" {
  name                         = "${var.resource_prefix}-wanPIP"
  location                     = var.location
  resource_group_name          = azurerm_resource_group.rg.name
  allocation_method            = "Static"
}

# Create Network Security Group and rule
resource "azurerm_network_security_group" "nsg" {
  name                = "${var.resource_prefix}-nsg"
  location            = var.location
  resource_group_name = "${azurerm_resource_group.rg.name}"

  security_rule {
    name                       = "SSH"
    priority                   = 1001
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }

  security_rule {
    name                       = "HTTP"
    priority                   = 1002
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }

  security_rule {
    name                       = "HTTPS"
    priority                   = 1003
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "443"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}

# Create network interface for netscaler wan
resource "azurerm_network_interface" "wannic" {
  name                      = "${var.resource_prefix}-wannic"
  location                  = var.location
  resource_group_name       = azurerm_resource_group.rg.name
  network_security_group_id = azurerm_network_security_group.nsg.id

  ip_configuration {
      name                          = "${var.resource_prefix}-mgmtipconfig"
      subnet_id                     = azurerm_subnet.wansubnet.id
      private_ip_address_allocation = "static"
      private_ip_address            = "10.10.1.4"
      public_ip_address_id          = azurerm_public_ip.mgmtpip.id
      primary                       = true
  }

  ip_configuration {
    name                          = "${var.resource_prefix}-wanipconfig"
    subnet_id                     = azurerm_subnet.wansubnet.id
    private_ip_address_allocation = "static"
    private_ip_address            = "10.10.1.5"
    public_ip_address_id          = azurerm_public_ip.wanpip.id
    primary                       = false
  }
}

# Create network interface for netscaler lan
resource "azurerm_network_interface" "lannic" {
  name                      = "${var.resource_prefix}-lannic"
  location                  = var.location
  resource_group_name       = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "${var.resource_prefix}-lanipconfig"
    subnet_id                     = azurerm_subnet.lansubnet.id
    private_ip_address_allocation = "static"
    private_ip_address            = "10.10.2.4"
  }
}


# Create Netscaler virtual machine
resource "azurerm_virtual_machine" "vm" {
  name                  = "${var.resource_prefix}-vm"
  location              = var.location
  resource_group_name   = azurerm_resource_group.rg.name
  network_interface_ids = [
    "${azurerm_network_interface.wannic.id}",
    "${azurerm_network_interface.lannic.id}"
  ]
  primary_network_interface_id = "${azurerm_network_interface.wannic.id}"
  vm_size               = "Standard_A2"

  storage_image_reference {
    publisher = "citrix"
    offer     = "netscalervpx-130"
    sku       = "netscaler10platinum"
    version   = "130.41.28"
  }

  plan {
    name = "netscaler10platinum"
    publisher = "citrix"
    product = "netscalervpx-130"
  }
  
storage_os_disk {
    name              = "${var.resource_prefix}OsDisk"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }

  os_profile {
    computer_name  = "${var.resource_prefix}-vm"
    admin_username = var.admin_username
    admin_password = var.admin_password
  }

  os_profile_linux_config {
    disable_password_authentication = false
  }


# Perform the following commands over CLI

  provisioner "remote-exec" {
    connection {
      host     = azurerm_public_ip.mgmtpip.ip_address 
      type     = "ssh"
      user     = var.admin_username
      password = var.admin_password
    }

    inline = [
      "add ns ip 10.10.1.5 255.255.255.0 -type vip",
      "add ns ip 10.10.2.4 255.255.255.0 -type snip",
      "save config"
    ]
  }
}

Environment (please complete the following information):

  • OS: N/A
  • Azure CloudShell
  • azurerm 1.36.1_x4
  • Citrix ADC 13.0

Error unbinding ssl profile from cs vserver

Hello.
After enabling default ssl profile terraform can't destroy cs vs with SSL type, if it binded to default ssl profile.

Error: [ERROR] netscaler-provider: Error unbinding ssl profile from csvserver tf-10.0.0.2_443_SSL
on .terraform/modules/create_http_balancer/main.tf line 20, in resource "citrixadc_csvserver" "resource_vpx_csvs":
20: resource "citrixadc_csvserver" "resource_vpx_csvs" {

Reproduce:

  1. adc cli: set ssl parameter -defaultProfile ENABLED
  2. apply resource "citrixadc_csvserver" without specific sslprofile.
    For example:
    '
    resource "citrixadc_csvserver" "resource_vpx_csvs" {
    name = "tf-10.0.0.2_443_SSL"
    ipv46 = "10.0.0.2"
    port = "443"
    servicetype = "SSL"
    sslcertkey = citrixadc_sslcertkey.generic-cert.certkey
    #sslprofile = "ns_default_ssl_profile_frontend"
    '
  3. destroy resource "citrixadc_csvserver"

Can't add server name to service group members

Hi,

I am trying to add a specific server name when I try to add a service group member to a service group using terraform. I see in the code for service group that currently the only things that are being parsed out from the arguments are:
IP Address, Port and Weight.

servicegroupMembers := make([]string, 0, len(boundMembers))
	for _, member := range boundMembers {
		ip := member["ip"].(string)
		port := member["port"].(float64) //TODO: why is this not int?
		weight := member["weight"].(string)
		strmember := fmt.Sprintf("%s:%.0f:%s", ip, port, weight)
		servicegroupMembers = append(servicegroupMembers, strmember)
	}
	d.Set("servicegroupmembers", servicegroupMembers)

Can we have the ability to add a server name to this list so that its easier to find the servers in a service group by their names rather than IP address?

There is an argument that could be passed in the API call to add a server name:
d.Set("servername", data["servername"])

Thanks

sslcertkey attribute of lbvserver not refreshing properly when CA certificates are bound

Describe the bug
Resource citrixadc_lbvserver does not refresh sslcertkey attribute properly when CA certificates are bound to virtual server.

To reproduce
Steps to reproduce the behavior:

Attempt to update a citrixadc_lbvserver resource with an sslcertkey attribute, while the virtual server has a CA certificate bound.

Terraform configuration:

variable "netscaler" {
    description = "Map for Nitro API access information.  It has attributes hostname, username, and password."
    type = object({hostname = string, username = string, password = string})
}

variable "virtualserver_ip" {
    description = "virtual server IP address"
}

variable "server_cert" {
    description = "Server certificate name"
}

variable "ca_chain" {
    description = "Map with CA certificate chain names.  It has attributes int and root."
    type = object({int = string, root = string})
}

locals {
        endpoint = "https://${var.netscaler.hostname}/"
}

provider "citrixadc" {
    endpoint = local.endpoint
    username = var.netscaler.username
    password = var.netscaler.password
    insecure_skip_verify = true
}

resource "citrixadc_lbvserver" "ssl_virtualserver" {
        name = "certkey-error-test"
        ipv46 = var.virtualserver_ip
        port = 443
        servicetype = "SSL"
        persistencetype = "SSLSESSION"
        sslcertkey = var.server_cert

        provisioner "local-exec" {
        command = <<HERE
sshpass -p ${var.netscaler.password} ssh -o StrictHostKeyChecking=no ${var.netscaler.username}@${var.netscaler.hostname} <<DOC
bind ssl vserver ${self.name} -certkeyName ${var.ca_chain.int} -CA -ocspCheck Optional
bind ssl vserver ${self.name} -certkeyName ${var.ca_chain.root} -CA -ocspCheck Optional
DOC
        HERE
        }
}

Expected behavior
CA certificates bound to a virtual server will have no bearing on the sslcertkey attribute within a citrixadc_lbvserver resource.

Logs

Error output below. Sanitized trace logs can be obtained as well if necessary.

terraform@machine:~/CitrixADC_Certkey_Error$ terraform apply --var-file input.tfvars 

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # citrixadc_lbvserver.ssl_virtualserver will be created
  + resource "citrixadc_lbvserver" "ssl_virtualserver" {
      + appflowlog                         = (known after apply)
      + authentication                     = (known after apply)
      + authenticationhost                 = (known after apply)
      + authn401                           = (known after apply)
      + authnprofile                       = (known after apply)
      + authnvsname                        = (known after apply)
      + backuplbmethod                     = (known after apply)
      + backuppersistencetimeout           = (known after apply)
      + backupvserver                      = (known after apply)
      + bypassaaaa                         = (known after apply)
      + cacheable                          = (known after apply)
      + clttimeout                         = (known after apply)
      + comment                            = (known after apply)
      + connfailover                       = (known after apply)
      + cookiename                         = (known after apply)
      + datalength                         = (known after apply)
      + dataoffset                         = (known after apply)
      + dbprofilename                      = (known after apply)
      + dbslb                              = (known after apply)
      + disableprimaryondown               = (known after apply)
      + dns64                              = (known after apply)
      + dnsprofilename                     = (known after apply)
      + downstateflush                     = (known after apply)
      + hashlength                         = (known after apply)
      + healththreshold                    = (known after apply)
      + httpprofilename                    = (known after apply)
      + httpsredirecturl                   = (known after apply)
      + icmpvsrresponse                    = (known after apply)
      + id                                 = (known after apply)
      + insertvserveripport                = (known after apply)
      + ipmask                             = (known after apply)
      + ippattern                          = (known after apply)
      + ipset                              = (known after apply)
      + ipv46                              = "10.1.1.20"
      + l2conn                             = (known after apply)
      + lbmethod                           = (known after apply)
      + lbprofilename                      = (known after apply)
      + listenpolicy                       = (known after apply)
      + listenpriority                     = (known after apply)
      + m                                  = (known after apply)
      + macmoderetainvlan                  = (known after apply)
      + maxautoscalemembers                = (known after apply)
      + minautoscalemembers                = (known after apply)
      + mssqlserverversion                 = (known after apply)
      + mysqlcharacterset                  = (known after apply)
      + mysqlprotocolversion               = (known after apply)
      + mysqlservercapabilities            = (known after apply)
      + mysqlserverversion                 = (known after apply)
      + name                               = "certkey-error-test"
      + netmask                            = (known after apply)
      + netprofile                         = (known after apply)
      + newname                            = (known after apply)
      + newservicerequest                  = (known after apply)
      + newservicerequestincrementinterval = (known after apply)
      + newservicerequestunit              = (known after apply)
      + oracleserverversion                = (known after apply)
      + persistencebackup                  = (known after apply)
      + persistencetype                    = "SSLSESSION"
      + persistmask                        = (known after apply)
      + port                               = 443
      + pq                                 = (known after apply)
      + processlocal                       = (known after apply)
      + push                               = (known after apply)
      + pushlabel                          = (known after apply)
      + pushmulticlients                   = (known after apply)
      + pushvserver                        = (known after apply)
      + range                              = (known after apply)
      + recursionavailable                 = (known after apply)
      + redirectfromport                   = (known after apply)
      + redirectportrewrite                = (known after apply)
      + redirurl                           = (known after apply)
      + redirurlflags                      = (known after apply)
      + resrule                            = (known after apply)
      + retainconnectionsoncluster         = (known after apply)
      + rhistate                           = (known after apply)
      + rtspnat                            = (known after apply)
      + rule                               = (known after apply)
      + sc                                 = (known after apply)
      + servicename                        = (known after apply)
      + servicetype                        = "SSL"
      + sessionless                        = (known after apply)
      + skippersistency                    = (known after apply)
      + sobackupaction                     = (known after apply)
      + somethod                           = (known after apply)
      + sopersistence                      = (known after apply)
      + sopersistencetimeout               = (known after apply)
      + sothreshold                        = (known after apply)
      + sslcertkey                         = "serverCert"
      + state                              = (known after apply)
      + tcpprofilename                     = (known after apply)
      + td                                 = (known after apply)
      + timeout                            = (known after apply)
      + tosid                              = (known after apply)
      + trofspersistence                   = (known after apply)
      + v6netmasklen                       = (known after apply)
      + v6persistmasklen                   = (known after apply)
      + vipheader                          = (known after apply)
      + weight                             = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

citrixadc_lbvserver.ssl_virtualserver: Creating...
citrixadc_lbvserver.ssl_virtualserver: Provisioning with 'local-exec'...
citrixadc_lbvserver.ssl_virtualserver (local-exec): Executing: ["/bin/sh" "-c" "sshpass -p password ssh -o StrictHostKeyChecking=no username@ipaddress <<DOC\r\nbind ssl vserver certkey-error-test -certkeyName ca_int -CA -ocspCheck Optional\r\nbind ssl vserver certkey-error-test -certkeyName ca_root -CA -ocspCheck Optional\r\nDOC\r\n"]
citrixadc_lbvserver.ssl_virtualserver (local-exec): Pseudo-terminal will not be allocated because stdin is not a terminal.

citrixadc_lbvserver.ssl_virtualserver (local-exec):  Done
citrixadc_lbvserver.ssl_virtualserver (local-exec):  Done
citrixadc_lbvserver.ssl_virtualserver (local-exec):  Done
citrixadc_lbvserver.ssl_virtualserver (local-exec): ^D

citrixadc_lbvserver.ssl_virtualserver (local-exec): Fatal Exception!: EOF
citrixadc_lbvserver.ssl_virtualserver (local-exec): Bye!
citrixadc_lbvserver.ssl_virtualserver: Creation complete after 1s [id=certkey-error-test]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
terraform@machine:~/CitrixADC_Certkey_Error$ terraform apply --var-file input.tfvars 
citrixadc_lbvserver.ssl_virtualserver: Refreshing state... [id=certkey-error-test]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # citrixadc_lbvserver.ssl_virtualserver will be updated in-place
  ~ resource "citrixadc_lbvserver" "ssl_virtualserver" {
        appflowlog                         = "ENABLED"
        authentication                     = "OFF"
        authn401                           = "OFF"
        backuplbmethod                     = "ROUNDROBIN"
        backuppersistencetimeout           = 2
        bypassaaaa                         = "NO"
        cacheable                          = "NO"
      ~ ciphers                            = [
          - "DEFAULT",
        ]
        connfailover                       = "DISABLED"
        disableprimaryondown               = "DISABLED"
        dns64                              = "DISABLED"
        downstateflush                     = "ENABLED"
        hashlength                         = 0
        icmpvsrresponse                    = "PASSIVE"
        id                                 = "certkey-error-test"
        insertvserveripport                = "OFF"
        ipmask                             = "*"
        ippattern                          = "0.0.0.0"
        ipv46                              = "10.1.1.20"
        l2conn                             = "OFF"
        lbmethod                           = "LEASTCONNECTION"
        listenpolicy                       = "NONE"
        listenpriority                     = 0
        m                                  = "IP"
        macmoderetainvlan                  = "DISABLED"
        mysqlcharacterset                  = 0
        mysqlprotocolversion               = 0
        mysqlservercapabilities            = 0
        name                               = "certkey-error-test"
        newservicerequest                  = 0
        newservicerequestincrementinterval = 0
        newservicerequestunit              = "PER_SECOND"
        persistencebackup                  = "NONE"
        persistencetype                    = "SSLSESSION"
        persistmask                        = "255.255.255.255"
        port                               = 443
        processlocal                       = "DISABLED"
        push                               = "DISABLED"
        pushlabel                          = "none"
        pushmulticlients                   = "NO"
        redirectfromport                   = 0
        redirectportrewrite                = "DISABLED"
        redirurlflags                      = false
        retainconnectionsoncluster         = "NO"
        rhistate                           = "PASSIVE"
        rtspnat                            = "OFF"
        servicetype                        = "SSL"
        sessionless                        = "DISABLED"
        skippersistency                    = "None"
        snisslcertkeys                     = []
        somethod                           = "NONE"
        sopersistence                      = "DISABLED"
        sothreshold                        = 0
      ~ sslcertkey                         = "ca_root" -> "serverCert"
        timeout                            = 2
        tosid                              = 0
        trofspersistence                   = "ENABLED"
        v6netmasklen                       = 0
        weight                             = 0
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

citrixadc_lbvserver.ssl_virtualserver: Modifying... [id=certkey-error-test]

Error: [ERROR] netscaler-provider: Error unbinding sslcertkey from lbvserver ca_root

  on main.tf line 30, in resource "citrixadc_lbvserver" "ssl_virtualserver":
  30: resource "citrixadc_lbvserver" "ssl_virtualserver" {

Environment
OS: Ubuntu 16.04.6 LTS
Terraform version: 0.12.23
CitrixADC version: 0.12.11

Additional context
It appears that the ability to bind CA certificates to a virtual server, for use with client authentication, has not been implemented in the provider yet. As a workaround, it is necessary to perform this binding using a local-exec provisioner, which uses SSH to configure the Netscaler and perform the binding. This works fine upon first apply. However, subsequent applies incorrectly determine that the CA certificate is bound as the server certificate, when the provider performs a refresh. This results in the provider attempting to update the sslcertkey attribute of the citrixadc_lbvserver resource. This ultimately fails, as the provider is unable to unbind the CA certificate from the virtual server, in order to bind the server certificate.

The configuration does configure the Netscaler appropriately, and the server certificate and two CA certificates are bound appropriately to the virtual server, following an apply. However, the error on subsequent applies is preventing the Terraform run from completing, and therefore not pushing all intentional configuration changes. For instance, future changes to the virtual server do not succeed with consistency.

Updating (changing) sslcertkey fails

Following up on only send nodomaincheck on certificate change #39: I'm trying to change the certificate by uploading .cert and .key files with the same filename, but different content.
I'm using local-exec to actually upload the certificate files.

EXPECTED RESULT:
Changed sslcertkey object

ACTUAL RESULT:
Error: Error applying plan

STEPS TO REPRODUCE:

resources.tf

resource "null_resource" "destroy_certificate" {
  count = "${var.ingress["service_type"] == "SSL" ? 1 : 0}"

  provisioner "local-exec" {
    when = "destroy"
    command = "./cert_files.sh absent"
    working_dir = "${var.cwd}"
    environment = {
      TF_VAR_ns_ingress_name = "${var.ingress["name"]}"
    }
  }
}


resource "null_resource" "upload_certificate" {
  count = "${var.ingress["service_type"] == "SSL" ? 1 : 0}"

  triggers = {
    cert_hash = "${sha1(var.ingress["cert"])}"
  }

  provisioner "local-exec" {
    command = "./cert_files.sh absent"
    working_dir = "${var.cwd}"
    environment = {
      TF_VAR_ns_ingress_name = "${var.ingress["name"]}"
    }
  }
  provisioner "local-exec" {
    command = "./cert_files.sh present"
    working_dir = "${var.cwd}"
    environment = {
      TF_VAR_ns_ingress_name = "${var.ingress["name"]}"
    }
  }
}


resource "netscaler_sslcertkey" "lbsslcertkey" {
  count = "${var.ingress["service_type"] == "SSL" ? 1 : 0}"

  certkey = "TLS_${var.ingress["name"]}_${var.serial}"
  cert = "/nsconfig/ssl/${var.ingress["name"]}.cert"
  key = "/nsconfig/ssl/${var.ingress["name"]}.key"
  expirymonitor = "DISABLED"
  # notificationperiod = 90
  inform = "PEM"
  nodomaincheck = true

  depends_on = ["null_resource.upload_certificate"]
}


resource "netscaler_lbmonitor" "lbmonitor" {
  monitorname = "mon_${var.ingress["name"]}"
  type = "${var.backends_config["service_type"]}"
  interval = 350
  resptimeout = 250
}


resource "netscaler_server" "backends" {
  count = "${length(var.backends)}"

  name = "srv_${format("%s_%s", var.ingress["name"], replace(var.backends[count.index], "/[:.]+/", ""))}"
  ipaddress = "${var.backends[count.index]}"
}


resource "netscaler_servicegroup" "backend" {
  servicegroupname = "sg_${var.ingress["name"]}"
  lbvservers = ["${netscaler_lbvserver.lbvserver.name}"]
  servicetype = "${var.backends_config["service_type"]}"
  servicegroupmembers_by_servername = ["${formatlist("%s:%s", netscaler_server.backends.*.name, var.backends_config["port"])}"]
}


resource "netscaler_lbvserver" "lbvserver" {
  name = "lbvs_${var.ingress["name"]}"
  ipv46 = "${var.ingress["ip"]}"
  port = "${var.ingress["port"]}"
  servicetype = "${var.ingress["service_type"]}"
  lbmethod = "ROUNDROBIN"
  persistencetype = "COOKIEINSERT"
  # ugly workaround to conditionally reference a possible 0 count resource:
  sslcertkey = "${element(concat(netscaler_sslcertkey.lbsslcertkey.*.certkey, list("")), 0)}"
}

variables.tf

variable "ns_user" {
  default = "nsroot"
}

variable "ns_password" {
  default = "nsroot"
}

variable "ns_hostname" {
  default = "ns.domain.tld"
}

variable "cwd" {
  default = "."
}

variable "serial" {
  default = ""
}

variable "ingress" {
  type = "map"
  "description" = "name, vip, port and servicetype for the load balancer"
  default {
    port = 443
    service_type = "SSL"
  }
}

variable "backends_config" {
  type = "map"
  "description" = "port and servicetype for the backend services"
  default {
    clttimeout = 40
    backend_port = 80
    service_type = "HTTP"
  }
}

variable "backends" {
  type = "list"
  description = "List of backend services [ipaddress:port]"
}
ingress = {
  name = "ademoapp"
  service_type = "SSL"
  ip = "10.42.42.100"
  port = 443

  cert = <<EOF
-----BEGIN CERTIFICATE-----
<snip>
-----END CERTIFICATE-----
EOF

}

backends_config = {
  clttimeout = 40
  port = 80
  service_type = "HTTP"
}

backends = [
  "10.42.42.1",
  "10.42.42.2",
  "10.42.42.3",
]

Create initial setup

export TF_CLI_CONFIG_FILE=terraformrc
export TF_VAR_cwd=/home/user/netscaler/terraform
export TF_VAR_ns_hostname=ns.domain.tld
export TF_VAR_ns_ingress_name=ademoapp
export TF_VAR_ns_password=Pssssh
export TF_VAR_ns_user=my_username
export TF_VAR_serial=9b464bfc0efeb1fd

terraform apply -parallelism=1 -refresh=true -no-color \
  -state app_states/ademoapp.tfstate \
  -var-file=app_vars/ademoapp.tfvars

Resulting state

terraform show app_states/ademoapp.tfstate

netscaler_lbmonitor.lbmonitor:
  id = mon_ademoapp
  action = Not applicable
  alertretries = 0
  application =
  attribute =
  basedn =
  binddn =
  customheaders =
  database =
  destip =
  destport = 0
  dispatcherip = 0.0.0.0
  dispatcherport = 0
  domain =
  downtime = 30
  evalrule =
  failureretries = 0
  filename =
  filter =
  group =
  hostipaddress =
  hostname =
  httprequest = HEAD /
  inbandsecurityid = NO_INBAND_SECURITY
  interval = 350
  iptunnel = NO
  kcdaccount =
  lasversion =
  logonpointname =
  lrtm =
  metric =
  metrictable =
  metricthreshold = 0
  metricweight = 0
  monitorname = mon_ademoapp
  mssqlprotocolversion =
  netprofile =
  oraclesid =
  originhost =
  originrealm =
  password =
  productname =
  query =
  querytype =
  radaccountsession =
  radapn =
  radframedip = 0.0.0.0
  radkey =
  radmsisdn =
  radnasid =
  radnasip = 0.0.0.0
  recv =
  respcode.# = 1
  respcode.0 = 200
  resptimeout = 250
  retries = 3
  reverse = NO
  rtsprequest = HEAD /
  scriptargs =
  scriptname =
  secondarypassword =
  secure = NO
  send =
  servicegroupname =
  servicename =
  sipmethod = OPTIONS
  sipreguri =
  sipuri =
  sitepath =
  snmpcommunity =
  snmpoid =
  snmpthreshold =
  snmpversion = V1
  sqlquery =
  sslprofile =
  state = ENABLED
  storedb = DISABLED
  storefrontacctservice = NO
  storefrontcheckbackendservices = NO
  storename =
  successretries = 1
  tos = NO
  tosid = 0
  transparent = NO
  trofsstring =
  type = HTTP
  units1 = SEC
  units2 = SEC
  units3 = SEC
  units4 = SEC
  username =
  validatecred =
  vendorspecificvendorid = 0
netscaler_lbvserver.lbvserver:
  id = lbvs_ademoapp
  appflowlog = ENABLED
  authentication = OFF
  authenticationhost =
  authn401 = OFF
  authnprofile =
  authnvsname =
  backuplbmethod =
  backuppersistencetimeout = 2
  backupvserver =
  bypassaaaa = NO
  cacheable = NO
  comment =
  connfailover = DISABLED
  cookiename =
  dbprofilename =
  dbslb =
  disableprimaryondown = DISABLED
  dns64 = DISABLED
  dnsprofilename =
  downstateflush = ENABLED
  hashlength = 0
  httpprofilename =
  httpsredirecturl =
  icmpvsrresponse = PASSIVE
  insertvserveripport = OFF
  ipmask = *
  ippattern = 0.0.0.0
  ipset =
  ipv46 = 10.42.42.100
  l2conn = OFF
  lbmethod = ROUNDROBIN
  lbprofilename =
  listenpolicy = NONE
  listenpriority = 0
  m = IP
  macmoderetainvlan = DISABLED
  mssqlserverversion =
  mysqlcharacterset = 0
  mysqlprotocolversion = 0
  mysqlservercapabilities = 0
  mysqlserverversion =
  name = lbvs_ademoapp
  netmask =
  netprofile =
  newname =
  newservicerequest = 0
  newservicerequestincrementinterval = 0
  newservicerequestunit = PER_SECOND
  oracleserverversion =
  persistencebackup = NONE
  persistencetype = COOKIEINSERT
  persistmask = 255.255.255.255
  port = 443
  pq =
  processlocal = DISABLED
  push = DISABLED
  pushlabel = none
  pushmulticlients = NO
  pushvserver =
  recursionavailable =
  redirectfromport = 0
  redirectportrewrite = DISABLED
  redirurl =
  redirurlflags = false
  resrule =
  retainconnectionsoncluster = NO
  rhistate = PASSIVE
  rtspnat = OFF
  rule =
  sc =
  servicename =
  servicetype = SSL
  sessionless = DISABLED
  skippersistency = None
  sobackupaction =
  somethod = NONE
  sopersistence = DISABLED
  sothreshold = 0
  sslcertkey = TLS_ademoapp_9b464bfc0efeb1fd
  sslprofile =
  state =
  tcpprofilename =
  timeout = 2
  tosid = 0
  trofspersistence = ENABLED
  v6netmasklen = 0
  vipheader =
  weight = 0
netscaler_server.backends.0:
  id = srv_ademoapp_1042421
  comment =
  delay = 0
  domain =
  domainresolvenow = false
  domainresolveretry = 0
  graceful =
  internal = false
  ipaddress = 10.42.42.1
  ipv6address = NO
  name = srv_ademoapp_1042421
  newname =
  state = ENABLED
  translationip = 0.0.0.0
  translationmask = 0.0.0.0
netscaler_server.backends.1:
  id = srv_ademoapp_1042422
  comment =
  delay = 0
  domain =
  domainresolvenow = false
  domainresolveretry = 0
  graceful =
  internal = false
  ipaddress = 10.42.42.2
  ipv6address = NO
  name = srv_ademoapp_1042422
  newname =
  state = ENABLED
  translationip = 0.0.0.0
  translationmask = 0.0.0.0
netscaler_server.backends.2:
  id = srv_ademoapp_1042423
  comment =
  delay = 0
  domain =
  domainresolvenow = false
  domainresolveretry = 0
  graceful =
  internal = false
  ipaddress = 10.42.42.3
  ipv6address = NO
  name = srv_ademoapp_1042423
  newname =
  state = ENABLED
  translationip = 0.0.0.0
  translationmask = 0.0.0.0
netscaler_servicegroup.backend:
  id = sg_ademoapp
  appflowlog = ENABLED
  autodisabledelay = 0
  autodisablegraceful =
  autoscale = DISABLED
  cacheable = NO
  cachetype = SERVER
  cip = ENABLED
  cipheader = X-Forwarded-For
  cka = NO
  clttimeout = 180
  cmp = NO
  comment =
  customserverid =
  delay = 0
  downstateflush = ENABLED
  dupweight = 0
  graceful = NO
  healthmonitor = YES
  httpprofilename =
  includemembers = false
  lbmonitor =
  lbvservers.# = 1
  lbvservers.4129248370 = lbvs_ademoapp
  memberport = 0
  monconnectionclose = NONE
  monitornamesvc =
  netprofile =
  newname =
  pathmonitor = NO
  pathmonitorindv = NO
  port = 0
  riseapbrstatsmsgcode = 0
  rtspsessionidremap = OFF
  sc =
  serverid = 0
  servername =
  servicegroupmembers.# = 0
  servicegroupmembers_by_servername.# = 3
  servicegroupmembers_by_servername.1839026872 = srv_ademoapp_1042423:80:1
  servicegroupmembers_by_servername.2797699357 = srv_ademoapp_1042422:80:1
  servicegroupmembers_by_servername.542503859 = srv_ademoapp_1042421:80:1
  servicegroupname = sg_ademoapp
  servicetype = HTTP
  sp = OFF
  state = ENABLED
  svrtimeout = 360
  tcpb = NO
  tcpprofilename =
  useproxyport = YES
  usip = NO
  weight = 0
netscaler_sslcertkey.lbsslcertkey:
  id = TLS_ademoapp_9b464bfc0efeb1fd
  bundle =
  cert = /nsconfig/ssl/ademoapp.cert
  certkey = TLS_ademoapp_9b464bfc0efeb1fd
  expirymonitor = DISABLED
  fipskey =
  hsmkey =
  inform = PEM
  key = /nsconfig/ssl/ademoapp.key
  linkcertkeyname =
  nodomaincheck = false
  notificationperiod = 0
  ocspstaplingcache = false
  passplain =
  password = false
null_resource.destroy_certificate:
  id = 2452242766656250296
null_resource.upload_certificate:
  id = 4257515104869952010
  triggers.% = 1
  triggers.cert_hash = 66b0e9969c211e5a824b504d092802e57d9f3367

Changes

  • contents of certificate files : app_vars/ademoapp.cert, app_vars/ademoapp.key
  • cert var variable
  • name of lbsslcertkey to trigger change ("taint"), see TF_VAR_serial

app_vars/ademoapp.tfvars


ingress = {
  ....
  cert = <<EOF
-----BEGIN CERTIFICATE-----
MIIDmTCCAoGgAwIBAgIJAJtGS/wO/rH9MA0GCSqGSIb3DQEBCwUAMGsxCzAJBgNV
<snip>
-----END CERTIFICATE-----
...
}

Execute terraform again


export TF_CLI_CONFIG_FILE=terraformrc
export TF_VAR_cwd=/home/user/netscaler/terraform
export TF_VAR_ns_hostname=ns.domain.tld
export TF_VAR_ns_ingress_name=ademoapp
export TF_VAR_ns_password=Pssssh
export TF_VAR_ns_user=my_username
export TF_VAR_serial=123456789abcdef
terraform apply -parallelism=1 -refresh=true -no-color \
  -state app_states/ademoapp.tfstate \
  -var-file=app_vars/ademoapp.tfvars

null_resource.upload_certificate: Refreshing state... (ID: 4257515104869952010)
null_resource.destroy_certificate: Refreshing state... (ID: 2452242766656250296)
netscaler_server.backends[2]: Refreshing state... (ID: srv_ademoapp_1042423)
netscaler_server.backends[1]: Refreshing state... (ID: srv_ademoapp_1042422)
netscaler_server.backends[0]: Refreshing state... (ID: srv_ademoapp_1042421)
netscaler_lbmonitor.lbmonitor: Refreshing state... (ID: mon_ademoapp)
netscaler_sslcertkey.lbsslcertkey: Refreshing state... (ID: TLS_ademoapp_9b464bfc0efeb1fd)
netscaler_lbvserver.lbvserver: Refreshing state... (ID: lbvs_ademoapp)
netscaler_servicegroup.backend: Refreshing state... (ID: sg_ademoapp)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place
-/+ destroy and then create replacement

Terraform will perform the following actions:

~ netscaler_lbvserver.lbvserver
      sslcertkey:                                   "TLS_ademoapp_9b464bfc0efeb1fd" => "TLS_ademoapp_123456789abcdef"

  ~ netscaler_servicegroup.backend
      servicegroupmembers_by_servername.1839026872: "srv_ademoapp_1042423:80:1" => ""
      servicegroupmembers_by_servername.213590207:  "" => "srv_ademoapp_1042423:80"
      servicegroupmembers_by_servername.2796742708: "" => "srv_ademoapp_1042421:80"
      servicegroupmembers_by_servername.2797699357: "srv_ademoapp_1042422:80:1" => ""
      servicegroupmembers_by_servername.3020376026: "" => "srv_ademoapp_1042422:80"
      servicegroupmembers_by_servername.542503859:  "srv_ademoapp_1042421:80:1" => ""

  ~ netscaler_sslcertkey.lbsslcertkey
      certkey:                                      "TLS_ademoapp_9b464bfc0efeb1fd" => "TLS_ademoapp_123456789abcdef"
      nodomaincheck:                                "false" => "true"

-/+ null_resource.upload_certificate (new resource required)
      id:                                           "4257515104869952010" => <computed> (forces new resource)
      triggers.%:                                   "1" => "1"
      triggers.cert_hash:                           "66b0e9969c211e5a824b504d092802e57d9f3367" => "80c5376a34359caf831c1bef1724bb296764d1cd" (forces new resource)
Plan: 1 to add, 3 to change, 1 to destroy.



null_resource.upload_certificate: Destroying... (ID: 4257515104869952010)
null_resource.upload_certificate: Destruction complete after 0s
null_resource.upload_certificate: Creating...
  triggers.%:         "" => "1"
  triggers.cert_hash: "" => "80c5376a34359caf831c1bef1724bb296764d1cd"
null_resource.upload_certificate: Provisioning with 'local-exec'...
null_resource.upload_certificate (local-exec): Executing: ["/bin/sh" "-c" "./cert_files.sh absent"]
null_resource.upload_certificate: Provisioning with 'local-exec'...
null_resource.upload_certificate (local-exec): Executing: ["/bin/sh" "-c" "./cert_files.sh present"]
null_resource.upload_certificate: Creation complete after 12s (ID: 8026929991478337533)
netscaler_sslcertkey.lbsslcertkey: Modifying... (ID: TLS_ademoapp_9b464bfc0efeb1fd)
  certkey:       "TLS_ademoapp_9b464bfc0efeb1fd" => "TLS_ademoapp_123456789abcdef"
  nodomaincheck: "false" => "true"
netscaler_sslcertkey.lbsslcertkey: Modifications complete after 0s (ID: TLS_ademoapp_9b464bfc0efeb1fd)

Error: Error applying plan:

1 error(s) occurred:

* netscaler_lbvserver.lbvserver: netscaler_lbvserver.lbvserver: diffs didn't match during apply. This is a bug with Terraform and should be reported as a GitHub Issue.

Please include the following information in your report:

    Terraform Version: 0.11.13
    Resource ID: netscaler_lbvserver.lbvserver
    Mismatch reason: attribute mismatch: sslcertkey
    Diff One (usually from plan): *terraform.InstanceDiff{mu:sync.Mutex{state:0, sema:0x0}, Attributes:map[string]*terraform.ResourceAttrDiff{"sslcertkey":*terraform.ResourceAttrDiff{Old:"TLS_ademoapp_9b464bfc0efeb1fd", New:"TLS_ademoapp_123456789abcdef", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}}, Destroy:false, DestroyDeposed:false, DestroyTainted:false, Meta:map[string]interface {}(nil)}
    Diff Two (usually from apply): *terraform.InstanceDiff{mu:sync.Mutex{state:0, sema:0x0}, Attributes:map[string]*terraform.ResourceAttrDiff(nil), Destroy:false, DestroyDeposed:false, DestroyTainted:false, Meta:map[string]interface {}(nil)}

Also include as much context as you can about your config, state, and the steps you performed to trigger this error.


lbsslcertkey: only send nodomaincheck on certificate change

Issue description
lbsslcertkey won't accept the nodomaincheck attribute/argument on creating a certificate.
nodomaincheck is however needed in most cases to 'refresh' a certificate.

Steps to reproduce

Try this in a resources file.

resource "netscaler_sslcertkey" "lbsslcertkey" {
  certkey = "TLS_${lookup(var.vip, "name")}"
  cert = "/nsconfig/ssl/${lookup(var.vip, "name")}.cert"
  key = "/nsconfig/ssl/${lookup(var.vip, "name")}.key"
  expirymonitor = "DISABLED"
  nodomaincheck = true
}

Expected results : certificate created.
Actual results : certificate creation fails.

Remove nodomaincheck, upload new certificate files and rerun : success.

Further background information
The NITRO REST API distinguishes between add and change actions:
https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/ssl/sslcertkey/sslcertkey/#operations
where unfortunately ADD won't accept nodomaincheck, but change will.

Please detect the presence of a sslcertkey and send either add or change and only nodomaincheck on change.

terraform 12 supports conditional null arguments, I'm not sure if this would solve the issue, and in any case, we're not running v12 + supported netscaler provider :)

Can't update from 0.12.17 to 0.12.23 version Citrix Terraform Provider

Describe the bug
Can't update from 0.12.17 to 0.12.23 version Citrix Terraform Provider
After update i have error:
Error: [ERROR] go-nitro: FindResourceWithParams: non zero errorcode 1544

To Reproduce

  1. install Citrix Terraform Provider 0.12.17
  2. create file main.tf contains:
  • resource citrixadc_cspolicy
  • resource citrixadc_csvserver
  • resource citrixadc_lbvserver
  • resource citrixadc_servicegroup
  1. run terraform validate + plan + apply
  2. install Citrix Terraform Provider 0.12.23
  3. run terraform validate + plan + apply
    and you have error:
    Error: [ERROR] go-nitro: FindResourceWithParams: non zero errorcode 1544

Logs
citrix terraform provider upgrade (.17 to .23).txt

Environment (please complete the following information):

  • OS: centos7
  • Provider version [e.g. chrome, safari]
  • Terraform version 0.12.25
  • Citrix ADC version 0.12.17 and 0.12.23

would like to use transform

We are needing to use the transform piece in terraform to have a pipeline direct string type url for rewrite and then use that to say beginning pattern and post transform pattern.

Can i get some assistance on extending this ?

issue initializing v0.12.3 plugin with latest examples

PS D:\code\terraform-test\terraform-provider-citrixadc\examples\content_switch_ssl_lb_mon> terraform init -plugin-dir C:\Users\username\AppData
\Roaming\terraform.d\plugins

Initializing the backend...

Initializing provider plugins...

Missing required providers.

The following provider constraints are not met by the currently-installed
provider plugins:

* citrixadc (any version)

Terraform can automatically download and install plugins to meet the given
constraints, but this step was skipped due to the use of -get-plugins=false
and/or -plugin-dir on the command line.

If automatic installation is not possible or desirable in your environment,
you may manually install plugins by downloading a suitable distribution package
and placing the plugin's executable file in one of the directories given in
by -plugin-dir on the command line, or in the following directory if custom
plugin directories are not set:
    terraform.d/plugins/windows_amd64


Error: missing provider "citrixadc"

Describe the bug
Attempting to load latest plugin with latest code version results in Error: missing provider "citrixadc"

To Reproduce

  1. Download latest plugin binary
  2. Check out master
  3. Change directory to content_switch_ssl_lb_ mon example
  4. Run terraform init

Expected behavior
Expect plugin to load without issue

Environment (please complete the following information):

  • OS: Windows
  • Terraform version
    Terraform v0.12.8
  • Citrix ADC version
    v0.12.3

Additional context
Looking at the release notes, I think that this may be due to the netscaler to citrixadc rename. If I check out revision 21ff0f7ebef81ae3592d6b50fd76406aa1ea8bb9 and attempt to repro with latest plugin, there is no error and the plugin loads successfully.

When setting timeout to 0 on citrixadc_lbvserver , provider says successful but the value is set to default: 2 on netscaler

Describe the bug
We are trying to set the timeout value to 0 (persistence never times out unless browser is closed). When running apply, the plan is applied successfully but running additional plans shows that terraform wants to change value from 2 to 0.

To Reproduce

  • Create a citrixadc_lbvserver resource with timeout = "0"
  • Run tfm plan, tfm apply. Note the lbvserver is created successfully
  • Either inspect the state or run another plan. Terraform will want to change the value from 2 -> 0
  • Verify on the netscaler, the value is 2, not 0.

Expected behavior
The value on the netscaler lbvserver should be set to 0.

Logs
From citrixadc 12.1:
this is setting it from 1440 -> 0. (existing lbvserver)
I can set it fine to 2 or any value > than that

2020-06-01T16:32:54.001-0500 [DEBUG] plugin.terraform-provider-citrixadc_v0.12.21: 2020/06/01 16:32:54 [DEBUG] go-nitro: response Status: 400 Bad Request
2020-06-01T16:32:54.001-0500 [DEBUG] plugin.terraform-provider-citrixadc_v0.12.21: 2020/06/01 16:32:54 [INFO] go-nitro: error = { "errorcode": 1094, "message": "Too few arguments", "severity": "ERROR" }

Environment (please complete the following information):

  • OS: MacOS Catalina, Linux
  • Provider version: v0.12.21
  • Terraform version: v0.11.10
  • Citrix ADC version: 11.1 and 12.1 (I need to verify it is repeatable in both)

Additional context
It is unclear to me if this is a bug in the provider, or downstream in the go-nitro library being used.

Environment variables no longer work

Describe the bug
What is described in the readme no longer works for handling authentication to the ADC when the password is not default on the ADC.

To Reproduce
Follow the readme.

provider "citrixadc" {
username = "${var.ns_user}"
password = "${var.ns_password}"
endpoint = "http://10.71.136.250/"
}

In current version of terraform, it is advised to change to:

provider "citrixadc" {
username = "var.ns_user"
password = "var.ns_password"
endpoint = "http://10.71.136.250/"
}

"Terraform 0.11 and earlier required all non-constant expressions to be provided via interpolation syntax, but this pattern is now deprecated. To silence this warning, remove the "${ sequence from the start and the }" sequence from the end of this expression, leaving just the inner expression."

Expected behavior
Expect it to work.

Environment (please complete the following information):

  • OS: MacOS
  • Provider version v0.12.23
  • Terraform version v0.12.24
  • Citrix ADC version v13.0.41.28

Additional context
I have tried many other combinations to no avail to get it to work but nothing works. If I utilize the default nsroot password on the ADC and eliminate the username and password lines from the provider block, everything works fine.

Managing nsip resource

Hi,

Is there planned support for managing nsip resources?

I'm looking at replacing some puppetlabs-netscaler code and I have a requirement to manage HOSTROUTE injection and OSPF metrics.

I cant see any code or examples that support this.

Cheers,
Dave

RFE: New resource for sslvserver_sslcertkey_binding

Describe the feature
The one thing missing from the provider right now to make it easy to modularize is the option to add SNI certificates to an existing csvserver.

Currently new SNI certificates have to be added to an existing csvserver resource

resource "citrixadc_csvserver" "csv" {
  name        = "csv-dev"
  ipv46       = var.adc-vip
  servicetype = "SSL"
  port        = 443
  sslprofile  = "ssl_prof_tlsv12_tlsv13_sni"
  sslcertkey  = citrixadc_sslcertkey.default.certkey
  snisslcertkeys = [
    # every cert needs to be known here
  ]
}

Which means that if we create a publication type module for re-use we cannot use it with SSL certificates unless we want to create a new csverver for each publication.
Adding a sslvserver_sslcertkey_binding like this would be an easy option to have the modularization effect

resource "citrixadc_sslvserver_sslcertkey_binding" "binding" {
  vservername = var.already-existing-csvserver
  snicert     = citrixadc_sslcertkey.sni.certkey
}

The only issue is that this would conflict with the parameter in the above csvserver. But I think a simple warning that both shouldn't be used at the same time would suffice.

I would generally just do the PR for this but if you don't want any code contributions this is the best I can do.

Refresh forgots some existing resources

It looks to happening time to time that Terraform refresh does not found some existing Netscaler resources and it removes references to them from state file.

Example now I can see that Terraform would like to create this resource (even when it exists on Netscaler):

2018-08-02T08:20:02.3572881Z Terraform will perform the following actions:
2018-08-02T08:20:02.3580361Z 
2018-08-02T08:20:02.3642884Z   + netscaler_cspolicy.cspolicy_app[2]
2018-08-02T08:20:02.3658420Z       id:                                                            <computed>
2018-08-02T08:20:02.3673789Z       action:                                                        <computed>
2018-08-02T08:20:02.3691262Z       csvserver:                                                     "vip1"
2018-08-02T08:20:02.3709037Z       domain:                                                        <computed>
2018-08-02T08:20:02.3724084Z       logaction:                                                     <computed>
2018-08-02T08:20:02.3756748Z       newname:                                                       <computed>
2018-08-02T08:20:02.3774880Z       policyname:                                                    "iac-foo_server_policy_test"
2018-08-02T08:20:02.3884547Z       priority:                                                      "6003"
2018-08-02T08:20:02.3901476Z       rule:                                                          "HTTP.REQ.HEADER(\"host\").SET_TEXT_MODE(IGNORECASE).EQ(\"app.example.com\") && HTTP.REQ.URL.PATH.GET(1).SET_TEXT_MODE(IGNORECASE).CONTAINS(\"path\") && HTTP.REQ.URL.PATH.GET(2).SET_TEXT_MODE(IGNORECASE).CONTAINS(\"to\") && HTTP.REQ.HEADER(\"Cookie\").SET_TEXT_MODE(IGNORECASE).CONTAINS(\"foo=bar\")"
2018-08-02T08:20:02.3921307Z       targetlbvserver:                                               "iac-app_server_vslb_test"
2018-08-02T08:20:02.3939171Z       url:                                                           <computed>

And I can see that it is missing from state file.

But if I look earlier version of state file I can see that it have been there:

"netscaler_cspolicy.cspolicy_app.2": {
	"type": "netscaler_cspolicy",
	"depends_on": [
		"netscaler_csvserver.cs-ssl"
	],
	"primary": {
		"id": "iac-foo_server_policy_test",
		"attributes": {
			"action": "",
			"csvserver": "vip1",
			"domain": "",
			"id": "iac-foo_server_policy_test",
			"logaction": "",
			"policyname": "iac-foo_server_policy_test",
			"priority": "6003",
			"rule": "HTTP.REQ.HEADER(\"host\").SET_TEXT_MODE(IGNORECASE).EQ(\"app.example.com\") \u0026\u0026 HTTP.REQ.URL.PATH.GET(1).SET_TEXT_MODE(IGNORECASE).CONTAINS(\"path\") \u0026\u0026 HTTP.REQ.URL.PATH.GET(2).SET_TEXT_MODE(IGNORECASE).CONTAINS(\"to\") \u0026\u0026 HTTP.REQ.HEADER(\"Cookie\").SET_TEXT_MODE(IGNORECASE).CONTAINS(\"foo=bar\")",
			"targetlbvserver": "iac-app_server_vslb_test",
			"url": ""
		},
		"meta": {
			"schema_version": "1"
		},
		"tainted": false
	},
	"deposed": [],
	"provider": "provider.netscaler"
},

After this happens re-run Terraform refresh does not fix issue and only workaround which I know are:

  • Remove resource from Netscaler and let Terraform re-create them.
  • Manually update state file to missing sections (if you have backup from earlier versions).

Terraform version: v0.11.7
Netscaler provider version: v0.11.7.1

Don't ignore all errors from NITRO

Also, the SDK eats the meaning of the errors (such as 401) and prevents the underlying systems to know why something hapenned.

For example if you credentials are invalid, it will remove entries from your state file on an apply

Originally posted by @apetitbois in #17 (comment)

Can't change state of gslbservice from disabled=>enabled after initial set

Hi,

I am trying to do blue-green application deployments using GSLB as my application switch between blue-green application stack.

To begin with, I have my blue stack (lb_vserver->lb_servicegroup->servers) set as a "Disabled" service making traffic going only to my green stack (lb_vserver->lb_servicegroup->servers) which is set as an "enabled" gslbservice.

Now when I want to go in and do a application switch, I am trying to use terraform to update the state of my blue stack to "enabled" but I am getting the following errors on apply:

Error: Error applying plan:

1 error(s) occurred:

* netscaler_gslbservice.blue_stack_service_1: 1 error(s) occurred:

* netscaler_gslbservice.blue_stack_service_1: Error updating gslbservice <app>-<env>-blue-stack-service-ssl-443

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

From the log file I see that:

plugin.terraform-provider-netscaler_v0.11.10: 2019/07/24 13:09:16 [DEBUG] go-nitro: response Status: 599 Netscaler specific error
2019-07-24T13:09:16.105-0500 [DEBUG] plugin.terraform-provider-netscaler_v0.11.10: 2019/07/24 13:09:16 [INFO] go-nitro: error = { "errorcode": 278, "message": "Invalid argument [state]", "severity": "ERROR" }
2019/07/24 13:09:16 [TRACE] root: eval: *terraform.EvalWriteState
2019/07/24 13:09:16 [TRACE] root: eval: *terraform.EvalApplyProvisioners
2019/07/24 13:09:16 [TRACE] root: eval: *terraform.EvalIf
2019/07/24 13:09:16 [TRACE] root: eval: *terraform.EvalWriteState
2019/07/24 13:09:16 [TRACE] root: eval: *terraform.EvalWriteDiff
2019/07/24 13:09:16 [TRACE] root: eval: *terraform.EvalApplyPost
2019/07/24 13:09:16 [ERROR] root: eval: *terraform.EvalApplyPost, err: 1 error(s) occurred:

* netscaler_gslbservice.blue_stack_service_1: Error updating gslbservice <app>-<env>-blue-stack-service-ssl-443
2019/07/24 13:09:16 [ERROR] root: eval: *terraform.EvalSequence, err: 1 error(s) occurred:

* netscaler_gslbservice.blue_stack_service_1: Error updating gslbservice <app>-<env>-blue-stack-service-ssl-443

The plan for this update shows correct updates but while applying them it fails.

tfm plan
2019-07-24 13:30:05 [INFO] Git repository is at: ****
2019-07-24 13:30:05 [INFO] Validating terraform files ...
2019-07-24 13:30:06 [INFO] Verifying configured backend ...
2019-07-24 13:30:06 [INFO] Generating plan ...
  ~ netscaler_gslbservice.blue_stack_service_1
      state:   "DISABLED" => "ENABLED"

Please let me know what you think is happening here since this service enable-disable is an integral part of our blue-green application deployment.

Thanks

Implement save_config

As currently implemented, the NetScaler provider does not commit the configuration to the NetScaler's persistent store(CLI: save_config). Reason:

  1. TF parallelizes where it can and if each resource declaration tried to do a save_config then they could potentially stomp on each other. We would probably have to force serial execution.
  2. save_config takes 4-5 seconds. Currently, creating 12-15 resources using TF takes about 1 second. If each resource automatically saved the config then that would increase to 60-80 seconds.

One idea is to have a netscaler_save_config resource that could be run once. But it needs to run at the very end of the config run, so potentially the config author has to make it depend on every resource.
If and when TF implements depends_on support for modules (see hashicorp/terraform#10462) this could be solved by putting the 'main' config in a module and a second module that only runs netscaler_save_config and depends_on the first module

Usage on alpine docker image

Describe the bug
Running the terraform-provider-citrixadc does not work in an alpine docker image like the one shipped by Hashicorp for Terraform

To Reproduce

  • Run a container based on hashicorp/terraform:light image
  • Manually install the terraform-provider-citrixadc provider under .terraform/plugins folder
  • Run terraform init
  • Run terraform validate
    The failure occurs:
Failed to instantiate provider "registry.terraform.io/hashicorp/citrixadc" to obtain schema: fork/exec .terraform/plugins/registry.terraform.io/hashicorp/citrixadc/0.12.34/linux_amd64/terraform-provider-citrixadc_v0.12.34: no such file or directory

Expected behavior
Terraform validate should run without any issues.

Logs
Below is an example of what the pipeline output is when running the terraform validate after downloading the provider and placing it in .terraform/plugins folder

$ terraform init
Initializing modules...
Initializing the backend...
Initializing provider plugins...
- Using previously-installed hashicorp/citrixadc v0.12.34
- Using previously-installed hashicorp/vsphere v1.24.0
The following providers do not have any version constraints in configuration,
so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking
changes, we recommend adding version constraints in a required_providers block
in your configuration, with the constraint strings suggested below.
* hashicorp/citrixadc: version = "~> 0.12.34"
* hashicorp/vsphere: version = "~> 1.24.0"
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
$ terraform providers
Providers required by configuration:
.
β”œβ”€β”€ provider[registry.terraform.io/hashicorp/citrixadc]
β”œβ”€β”€ provider[registry.terraform.io/hashicorp/vsphere]
└── module.dsc_server
    └── provider[registry.terraform.io/hashicorp/vsphere]
Providers required by state:
    provider[registry.terraform.io/hashicorp/vsphere]
$ wget https://github.com/citrix/terraform-provider-citrixadc/releases/download/v0.12.34/terraform-provider-citrixadc_0.12.34_linux_amd64.tar.gz
Connecting to github.com (140.82.112.4:443)
Connecting to github-production-release-asset-2e65be.s3.amazonaws.com (52.217.13.228:443)
saving to 'terraform-provider-citrixadc_0.12.34_linux_amd64.tar.gz'
terraform-provider-c 100% |********************************| 8657k  0:00:00 ETA
'terraform-provider-citrixadc_0.12.34_linux_amd64.tar.gz' saved
$ tar -zxf terraform-provider-citrixadc_0.12.34_linux_amd64.tar.gz
$ rm README.md LICENSE terraform-provider-citrixadc_0.12.34_linux_amd64.tar.gz
$ cp terraform-provider-citrixadc .terraform/plugins/registry.terraform.io/hashicorp/citrixadc/0.12.34/linux_amd64/terraform-provider-citrixadc_v0.12.34
$ chmod 755 .terraform/plugins/registry.terraform.io/hashicorp/citrixadc/0.12.34/linux_amd64/terraform-provider-citrixadc_v0.12.34
$ terraform validate
Error: Could not load plugin
Plugin reinitialization required. Please run "terraform init".
Plugins are external binaries that Terraform uses to access and manipulate
resources. The configuration provided requires plugins which can't be located,
don't satisfy the version constraints, or are otherwise incompatible.
Terraform automatically discovers provider requirements from your
configuration, including providers used in child modules. To see the
requirements and constraints, run "terraform providers".
Failed to instantiate provider "registry.terraform.io/hashicorp/citrixadc" to
obtain schema: fork/exec
.terraform/plugins/registry.terraform.io/hashicorp/citrixadc/0.12.34/linux_amd64/terraform-provider-citrixadc_v0.12.34:
no such file or directory
ERROR: Job failed: exit code 1

Environment (please complete the following information):

  • OS: CentOS 8
  • Provider version [e.g. chrome, safari]
  • Terraform version 0.13.3
  • Citrix ADC version 12.1

Additional context
The issue happens in the pipeline I am running to configure lbservers in a VPX. This is important for us as we are moving to infrastructure as code. Having this provider working in an alpine-based image is important for anyone using docker containers to run pipelines.

I am not a go programmer but I believe this can be achieved by adding the following πŸ‘

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build

Missing ability to create and bind policypatset objects.

Describe the bug

As far as I can see (and apologies if I just missed it!), policydataset objects are present, policypatset ones are not. We've had to resort to (a lot of) suboptimal use of curl calls to the NITRO API to create and bind them. It would be good to get this capability native to the provider so we can have proper lifecycle control etc which is not readily possible using a null provider, exec provisioner and curl while also injecting credentials for the call securely.policypatset_pattern_binding

PS. Thanks for sorting issue #132 (I'll test it soonish), there's this one and no doubt more to come as we are only part way through a significant project with this provider. Figured it best to raise issues against this provider as an when they become notable rather than just bombard you with loads of noted issues when I've got everything working using workarounds, at which point it would be harder to justify going back and testing again.

These are the NITRO API endpoints I mean:

/nitro/v1/config/policypatset
/nitro/v1/config/policypatset_pattern_binding

To Reproduce
Nothing can be reproduced, missing functionality.

Expected behavior

Be able to create policypatset and bindings using the native terraform provider objects.

Environment

I don't think it helps to know this, but as per ticket #132, only upgraded a bit since.

filter policy and cmp policy support.

Describe the bug

Support for 'add filter policy', 'add cmp policy' and bindings also appear to be missing, and will bite us soon. As per other tickets by me in relation to this provider.

In context I don't think these are mission critical, but would be good to have them soonish.

599 Netscaler specific error: Binding Monitor to GSLB Service

Hi,

ADC Provider: v12.6

I am trying to bind a "ping" monitor to my gslb service and I keep getting:

* module.<app>_gslb.citrixadc_gslbservice.gslb_service: 1 error(s) occurred:

* citrixadc_gslbservice.gslb_service: [ERROR] go-nitro: Failed to create resource of type gslbservice, name=<app>-443-SSL, err=failed: 599 Netscaler specific error ({ "errorcode": 2170, "message": "Monitor not bound to service", "severity": "ERROR" })

This is probably due to not having the correct configurations for gslbservice_lbmonitor_binding in the provider.

I tried doing a PUT on the following: https://<HOST>/nitro/v1/config/gslbservice_lbmonitor_binding/<app>-443-SSL
with this as the body:
{"gslbservice_lbmonitor_binding":{"monitor_name":"ping","servicename":"<app>-443-SSL","weight":1}} and it worked.

Can we please fix this in the provider asap?

Thanks

resource_sslcertkey does not link certificates correctly

Describe the bug
resource_sslcertkey does not use the linkcertkey attribute correctly.

It needs to initiate a link/unlink action instead of just including the value in the POST body.

To Reproduce
Steps to reproduce the behavior:

Just run the resource_sslcertkey with linkcertkey set to an existing certificate

Expected behavior
use link/unlink action not POST/PUT the value of linkcertkey with all other values

Logs
Use terraform TF_LOG https://www.terraform.io/docs/internals/debugging.html to get logs

Environment (please complete the following information):
Applies to all environments

Additional context
no additional context

Plugin version: 2, Ours: 4

Hi,

Thank you for sharing this plugin. I was wondering if I'm experiencing issues with this plugin vs my terraform latest version.

Which terraform or GO version should I use?

2017/04/28 23:32:27 [INFO] Terraform version: 0.9.4 277bbf65d1141207dbb30485bf124b1dba08f80f 2017/04/28 23:32:27 [INFO] Go runtime version: go1.8 2017/04/28 23:32:27 [INFO] CLI args: []string{"/usr/local/bin/terraform", "plan"}

2017/04/28 23:32:27 [DEBUG] plugin: starting plugin: /Users/ftorre2/work/src/github.com/citrix/terraform-provider-netscaler/terraform-provider-netscaler []string{"/Users/ftorre2/work/src/github.com/citrix/terraform-provider-netscaler/terraform-provider-netscaler"}
2017/04/28 23:32:27 [DEBUG] plugin: waiting for RPC address for: /Users/ftorre2/work/src/github.com/citrix/terraform-provider-netscaler/terraform-provider-netscaler
2017/04/28 23:32:27 [DEBUG] plugin: terraform-provider-netscaler: 2017/04/28 23:32:27 [DEBUG] plugin: plugin address: unix /var/folders/cz/x88_rb0d131gwxdq013bmqp1lzn11b/T/plugin699425407 2017/04/28 23:32:27 [ERROR] root: eval: *terraform.EvalInitProvider, err: Incompatible API version with plugin. Plugin version: 2, Ours: 4 2017/04/28 23:32:27 [ERROR] root: eval: *terraform.EvalSequence, err: Incompatible API version with plugin. Plugin version: 2, Ours: 4 2017/04/28 23:32:27 [DEBUG] dag/walk: upstream errored, not walking
"netscaler_lbvserver.production_lb" 2017/04/28 23:32:27 [DEBUG] dag/walk: upstream errored, not walking "netscaler_servicegroup.backend" 2017/04/28 23:32:27 [DEBUG] dag/walk: upstream errored, not walking "provider.netscaler (close)"
Error asking for user input: 1 error(s) occurred: provider.netscaler: Incompatible API version with plugin. Plugin version: 2, Ours: 4 2017/04/28 23:32:27 [DEBUG] plugin: waiting for all plugin processes to complete...

lbvserver should not be required parameter in citrixadc_service

Describe the bug
lbvserver property should not be required parameter in citrixadc_service.
Currently I'm getting The argument "lbvserver" is required, but no definition was found error.

To Reproduce
Try to create citrixadc_service resource without lbvserver parameter.

Expected behavior
You should be able to create service without binding it to lbvserver, as you can do in cli:

add lb vserver <name> <serviceType> <ip> <port>

Additional context

Ability to Dynamically bind service to gslb_vserver

Hi,

I am trying to use the citrixadc provider to create my GSLB configs. I want to be able to dynamically create "x' number of gslb_services based on my parameters and then bind them.

When I look at the code for gslb_vserver I see that every service has to be statically defined inside the resource, making it not possible for me to bind them dynamically.

Provider Version: v0.12.2
TF: v0.11.10

Current Code:

resource "netscaler_gslbservice" "gslb_service" {
  count          = "${length(var.service_name)}"
  ip             = "${element(var.service_ip, count.index)}"
  port           = "${lookup(var.ssl_config, "port")}"
  servicename    = "${format("%s-%s-%s-%s-%s", var.application,var.environment, element(var.service_name, count.index), lookup(var.ssl_config, "port"), lookup(var.ssl_config, "type"))}"
  servicetype    = "${lookup(var.ssl_config, "type")}"
  sitename       = "${lookup(local.netscaler_site, var.vsphere_environment)}"
  state          = "${element(var.service_state, count.index)}"
  monitornamesvc = "${var.service_monitor}"
}
resource "netscaler_gslbvserver" "gslb_vserver" {
  dnsrecordtype = "A"
  name          = "${format("%s-%s-gslb-%s-%s-%d", var.application,var.environment, lookup(var.ssl_config, "port"), lookup(var.ssl_config, "type"), count.index)}"
  servicetype   = "SSL"

  backupip = "${var.gslb_backup_ip}"

  domain {
    domainname = "${format("%s-%s.%s", var.application, var.environment, lookup(local.gslb_domain, var.vsphere_environment))}"
    ttl        = "60"
  }

  service {
    servicename = "${netscaler_gslbservice.gslb_service.0.servicename}"
    weight      = "100"
  }

  service {
    servicename = "${netscaler_gslbservice.gslb_service.1.servicename}"
    weight      = "100"
  }
}

There are 2 options here:

  1. If we could incorporate the ability to use a list in the servicename key of the service map in gslbvserver resource, that would add the ability to make this dynamic.

  2. If there was a way we could add count to the service map of gslbvserver resource:

service {
    count = "${length(netscaler_gslbservice.gslb_service.*.servicename)}"
    servicename = "${element(netscaler_gslbservice.gslb_service.*.servicename, count.index)}"
    weight      = "100"
}

Our organization can't currently upgrade to TF v12.

Please let me know if you need any more details.

Thanks.

lbvserver not setting `ciphers` correctly

I am new to using this provider within Terraform, but I am seeing odd behavior where the configuration is valid and says it is updating my SSL LB vServer with the correct cipher suite names, but I am not actually seeing it done when I login to the Web UI to check it - and my HTTPS LB endpoint is not working when there is not a cipher suite group set... any ideas?

Code:

resource "citrixadc_lbvserver" "netscaler_poc_lb" {
  name = "terraform_poc_lb"
  ipv46 = "x.x.x.x"
  port = 443
  servicetype = "SSL"
  lbmethod = "LEASTCONNECTION"
  sslcertkey = "cert-key-name"
  sslprofile = "ns_default_ssl_profile_secure_frontend"
  ciphers = ["Custom_CipherGroup_Name", "DEFAULT"]
}

resource "citrixadc_servicegroup" "netscaler_poc_service_group" {
  servicegroupname = "terraform_poc_service_group"
  servicetype = "HTTP"
  lbvservers = [citrixadc_lbvserver.netscaler_poc_lb.name]
  servicegroupmembers = ["x.x.x.x:80","x.x.x.x:80"]
}

Let me know if I can help with providing any other details. Basically the ciphers part seems to not be actually set, but there are 0 errors returned.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.