Closed fortinj66 closed 6 years ago
The documentation is wrong currently. Can you paste the playbook yaml? Trying to understand what you're trying to achieve.
How do I do the equivalent of:
echo "Binding mwgso-api.marketamerica.com_http to ${VIP}.policy”
${SSH} bind cs vserver mwgso-api.marketamerica.com_http -policyName ${VIP}.policy -targetLBVserver ${VIP}.http -priority ${PRIORITY}
This is what I was expecting to work:
I did see that.
My worry is that if I use it to add a new binding, the current bindings would be deleted.
Looks like you're attempting to manage only part of the configuration using Ansible? If so, I'm not sure it is a great idea. Also, the 'targetvserver' option is only for SSL VPN servers. You should only need to specify 'targetLbvserver' in your scenario
That puzzles me as all of our internal vservers are http (non-ssl) and we have to use the target vserver from the command line.
From my bash script:
${SSH} bind cs vserver mwgso-api.marketamerica.com_http -policyName ${VIP}.policy -targetLBVserver ${VIP}.http -priority ${PRIORITY}
and if you do the bind from the UI, you also have to select the target vserver before you can bind the target LBVserver...
The snippet abaove was a small part of the ansible script. The object of this script is to add a new microservice to the target vserver defined below. I should be able to add these one at a time. I have a bash script which works perfectly but doesn't integrate well into our deployment strategy.
This is the complete script:
- hosts: localhost
gather_facts: false
vars:
kubeconfig: ./kubeconfig
env: "none"
type: "java"
os_host_dev: "https://os-lb-d01.maeagle.corp:8443"
context_dev: "dev-microservices/os-lb-d01-maeagle-corp:8443/system:serviceaccount:internal-systems:micro-config"
api_key_dev:
os_host_prod: "https://console.prod.os.maeagle.corp:8443"
context_prod: "default/console-prod-os-maeagle-corp:8443/system:serviceaccount:internal-systems:micro-config"
api_key_prod:
os_env: "{{env | regex_replace('^stag.*', 'stage') | regex_replace('^dev.*', 'dev') | regex_replace('^(prod|live).*', 'prod')}}"
api_key: "{{os_env | regex_replace('(dev|stage)', api_key_dev) | regex_replace('prod', api_key_prod) }}"
os_host: "{{os_env | regex_replace('(dev|stage)', os_host_dev) | regex_replace('prod', os_host_prod) }}"
context: "{{os_env | regex_replace('(dev|stage)', context_dev) | regex_replace('prod', context_prod) }}"
prefix: "{{os_env | regex_replace('stage', 'stg') | regex_replace('prod', 'prd')}}"
namespace: "{{os_env +'-microservices'}}"
service_name: "none"
env_prefix: "{{os_env | regex_replace('(dev|stage)', 'd') | regex_replace('prod', 'p') }}"
heartbeat: "{{type | regex_replace('java', 'GET /'+service_name+'/application.wadl') | regex_replace('python', 'GET /'+service_name+'/heartbeat') }}"
service: "{{lookup('openshift', kubeconfig=kubeconfig, context=context, api_key=api_key, host=os_host, verify_ssl='no', api_version='v1', kind='Service', namespace=namespace, resource_name=service_name)}}"
node_port: "{{service.spec.ports[0].node_port}}"
vip: "{{prefix + '.' + service_name}}"
servicegroupname: "{{vip + '.' + node_port}}"
vserver_name: "{{vip + '.' + 'http'}}"
policyname: "{{vip + '.' + 'policy'}}"
targetvserver: "mwgso-api.marketamerica.com_http"
tasks:
- name: Check for valid environment
fail:
msg: "Environment '{{env}}' not defined or invalid. Add '-e env=[dev|staging|prod|live]'"
when: env|regex_search('^(dev|staging|prod|live)') is none
- name: Check for valid service
fail:
msg: "Service {{service_name}} does not exist"
when: service|length == 0
- name: Set lb monitor
netscaler_lb_monitor:
nsip: 10.102.0.3
nitro_user: xxx
nitro_pass: xxx
validate_certs: no
state: present
monitorname: "{{vip}}"
type: HTTP
respcode: ['200']
resptimeout: 5
httprequest: "{{heartbeat}}"
lrtm: disabled
interval: 30
- name: Setup http service group
netscaler_servicegroup:
nsip: 10.102.0.3
nitro_user: xxx
nitro_pass: xxx
validate_certs: no
state: present
servicegroupname: "{{servicegroupname}}"
servicetype: HTTP
cip: enabled
cipheader: X-Forwarded-For
cka: NO
cmp: YES
clttimeout: 180
svrtimeout: 360
maxclient: 0
maxreq: 0
tcpb: NO
useproxyport: YES
usip: NO
servicemembers:
- servername: "{{'os-node-'+env_prefix+'01'}}"
port: "{{node_port}}"
- servername: "{{'os-node-'+env_prefix+'02'}}"
port: "{{node_port}}"
- servername: "{{'os-node-'+env_prefix+'03'}}"
port: "{{node_port}}"
- servername: "{{'os-node-'+env_prefix+'04'}}"
port: "{{node_port}}"
monitorbindings:
- monitorname: "{{vip}}"
- name: Create a load balancing vserver bound to services
netscaler_lb_vserver:
nsip: 10.102.0.3
nitro_user: xxx
nitro_pass: xxx
validate_certs: no
state: present
name: "{{vserver_name}}"
servicetype: HTTP
clttimeout: 180
ipv46: 0.0.0.0
port: 0
persistencetype: NONE
servicegroupbindings:
- servicegroupname: "{{servicegroupname}}"
- name: Create url cs policy
netscaler_cs_policy:
nsip: 10.102.0.3
nitro_user: xxx
nitro_pass: xxx
validate_certs: no
state: present
policyname: "{{policyname}}"
rule: "HTTP.REQ.IS_VALID && HTTP.REQ.HOSTNAME.CONTAINS(\"{{env}}\") && HTTP.REQ.URL.PATH_AND_QUERY.STARTSWITH(\"/{{service_name}}\")"
- name: Configure netscaler content switching action
netscaler_cs_action:
nsip: 10.102.0.3
nitro_user: xxx
nitro_pass: xxx
validate_certs: no
state: present
name: "{{policyname}}"
targetlbvserver: "{{vserver_name}}"
targetvserver: "{{targetvserver}}"
- name: Save configuration
netscaler_save_config:
nsip: 10.102.0.3
nitro_user: xxx
nitro_pass: xxx
validate_certs: no
As I suspected, the module netscaler_cs_vserver.py will delete anything not configured in the playbook
That's a problem if all I want to do is add a new one.
def sync_cs_policybindings(client, module):
log('Syncing cs policybindings')
actual_bindings = get_actual_policybindings(client, module)
configured_bindings = get_configured_policybindings(client, module)
# Delete actual bindings not in configured
delete_keys = list(set(actual_bindings.keys()) - set(configured_bindings.keys()))
for key in delete_keys:
log('Deleting binding for policy %s' % key)
csvserver_cspolicy_binding.delete(client, actual_bindings[key])
# Add configured bindings not in actual
add_keys = list(set(configured_bindings.keys()) - set(actual_bindings.keys()))
for key in add_keys:
log('Adding binding for policy %s' % key)
configured_bindings[key].add()
# Update existing if changed
modify_keys = list(set(configured_bindings.keys()) & set(actual_bindings.keys()))
for key in modify_keys:
if not configured_bindings[key].has_equal_attributes(actual_bindings[key]):
log('Updating binding for policy %s' % key)
csvserver_cspolicy_binding.delete(client, actual_bindings[key])
configured_bindings[key].add()
The way to use cs action is to specify it as the action within a cs policy. For example:
add cs vserver test_csvserver HTTP 192.168.10.1 80
add lb vserver test_lbvserver
add cs action -targetLbvserver test_lbvserver
add cs policy test_cspolicy -rule HTTP.REQ.URL.PATH_AND_QUERY.STARTSWITH("/test") -action test_csaction
bind cs vserver test_csvserver -policyname test_cspolicy -priority 200
the targetvserver
in the cs action is not a cs vserver AFAIK, and is only used in SSL VPN.
if your lb vserver is named consistently according to the URL fragment, then you could create a cs action that selects the lb vserver based on the pattern.
add cs action mycsaction1 -targetvserverExpr '"mylb_" + HTTP.REQ.URL.SUFFIX
could you add all the existing policies to the playbook and manage all policies using Ansible?
Unfortunately, adding all the policies would be unmanageable. I have over 100 current policies running...
This is the methodology that I use from a script to accomplish the task:
${SSH} add serviceGroup ${VIP}.${PORT} HTTP -maxClient 0 -maxReq 0 -cip ENABLED X-Forwarded-For -usip NO -useproxyport YES -cltTimeout 180 -svrTimeout 360 -CKA NO -TCPB NO -CMP YES
for node in ${NODES}; do
echo "Binding service group ${VIP}.${PORT} to ${node}"
${SSH} bind serviceGroup ${VIP}.${PORT} ${node} ${PORT}
done
${SSH} add lb vserver ${VIP}.http HTTP 0.0.0.0 0 -persistenceType NONE -cltTimeout 180
${SSH} bind lb vserver ${VIP}.http ${VIP}.${PORT}
${SSH} add lb monitor ${VIP} HTTP -respCode 200 -httpRequest \"GET /${SERVICE}/application.wadl\" -LRTM DISABLED -interval 30 -resptimeout 5
${SSH} "add cs policy ${VIP}.policy -rule \"HTTP.REQ.IS_VALID && HTTP.REQ.HOSTNAME.CONTAINS(\\\"${ENV}\\\") && HTTP.REQ.URL.PATH_AND_QUERY.STARTSWITH(\\\"/${SERVICE}\\\")\""
${SSH} bind cs vserver mwgso-api.marketamerica.com_http -policyName ${VIP}.policy -targetLBVserver ${VIP}.http -priority ${PRIORITY}
${SSH} save nsconfig
if you adopt a naming scheme with the lb vserver
named as lb_${SERVICE}
then you may be able to use cs action
add cs action test_csaction -targetvserverExpr "lb_" + HTTP.REQ.URL.PATH.GET(1)
You would have only 1 policy to be bound to the cs vserver
regardless of ${SERVICE}
.
add cs policy test_cspolicy -rule \"HTTP.REQ.IS_VALID && HTTP.REQ.HOSTNAME.CONTAINS(\\\"${ENV}\\\") -action test_csaction
bind cs vserver mwgso-api.marketamerica.com_http -policyName test_cspolicy
In Ansible terms you wouldn't configure any policies or actions since these are one-time configuration.
I'm going to play with this a bit, but it may be easier to fork this and just add an option add/delete/sync rather than assume a sync...
I wrote a small script to export your existing policies into a playbook. See if it helps https://gist.github.com/chiradeep/b111a44cfc2bfb94fcbee6d7db35dab1
if you want the imperative style, I suggest enhancing the netscaler_nitro_request which supports such a mode. Currently it supports add/remove/rename and doesn't support bind/unbind
@fortinj66 should I close this?
For this particular case probably...
That being said, I still feel you should be able to add/delete a bind on an individual policy (especially since almost every other object can be handled individually) but the current framework seems to makes that difficult.
However, I was able to make the cs_action functionality work on our test systems to that will probable be my final solution...
Thanks for you help and insight into this issue.
--John
thanks for the feedback. opened a new issue https://github.com/citrix/netscaler-ansible-modules/issues/56
Trying to bind a policy to a cs virtual server and fails with the following. I am using the latest master git pull...
When I run the ansible task I get the following:
The code and the docs indicate that it should exist:
What is the correct way to add a binding if this module does not do it?
--John