Set ServiceNow "Server" field with a variable

#1

Hello all,

On all of the ServiceNow tasks from the ServiceNow Plugin, the “Server” field is required. However, it’s a list dropdown. I’m not able to set that as a variable.

What I’d like to do is to set a variable during the release to go out to either my production or non-production instance depending on what I’m testing.

Since It’d be much easier to change one variable at release time instead of go through all of the tasks and set them to another instance, does anybody know how that “Server” field can be set with a variable at release time or some other approach?

#2

Hi smacz,
The Variable substitution is not supported in the server field. However you can achieve it in a different way.

  • Create two shared configurations, one each for each server
  • Create a variable in the template to define the shared configuration name
  • Now in your template, create a new jython script task in the starting phase and you can refer to this code snippet https://github.com/xebialabs-community/xlr-jython-code-snippets#update-automated-task-server-entry
  • With this snippet, you can change it a little bit and use it to find the right server object that you want to use based on the value in the variable and then set it by updating the task(s)

If you want to update multiple tasks at one, you may use this snippet to understand how to iterate over all phases of a release and then all tasks under each phase https://github.com/xebialabs-community/xlr-jython-code-snippets#generate-a-markdown-table-with-phasetasktask-status-into-a-variable-for-using-in-email

Hope this helps !!

Amit

1 Like
#3

I’m having trouble with this part.

I’m doing the following:

servicenow_servers = configurationApi.searchByTypeAndTitle("servicenow.Server", releaseVariables['servicenow_instance'])
print(type(servicenow_servers))
for phase in release.phases:
    for task in phase.tasks:
        if str(task.getTaskType()).split('.')[0] == 'servicenow':
            print(task.pythonScript.getProperty('servicenowServer'))
            print(type(task.pythonScript.getProperty('servicenowServer')))
            print("\n")
            print(servicenow_servers[0])
            print(type(servicenow_servers[0]))
            print("\n")
            task.pythonScript.setProperty('servicenowServer', servicenow_servers[0])
            taskApi.updateTask(task)

And getting the following output:

<type 'list'> Configuration/Custom/Configuration3dacad8ce8d14937957b960ec2f848a3 <type 'com.xebialabs.xlrelease.domain.configuration.HttpConnection'>

Configuration/Custom/Configuration8b1ce7e06cb54b139c732e7396e5f845 <type 'instance'>

Exception during execution: java.lang.ClassCastException: java.lang.ClassCastException in <script> at line number 13

It looks like the property that is there is an “HttpConnection” property, and the one I found is an “instance” property. I can’t make one into the other, and I can’t make the code work!

#4

It seems you are mostly doing it right. Internally there is a base type for shared configurations called Configuration. The HttpConnection type is an extension to that. So it should be able to apply the servicenow_servers[0] of type Configuration to property servicenowServer that is a member of type HttpConnection. Maybe just to give another shot, type this notation and see if that works.

task.pythonscript.servicenowServer = servicenow_servers[0]

Amit

#5

Thanks for the response! Unfortunately, I’m getting a different error when I try setting it that way:

Exception during execution: AttributeError: 'com.xebialabs.xlrelease.domain.PythonScript' object has no attribute 'servicenowServer' in <script> at line number 5

Which doesn’t make sense to me since I was able to access it with .getProperty('servicenowServer')

#6

So it’s still not working. Here’s what I have so far:

servicenow_servers = configurationApi.searchByTypeAndTitle("servicenow.Server", releaseVariables['servicenow_instance'])
print("\n")
for phase in release.phases:
    for task in phase.tasks:
        if str(task.getTaskType()).split('.')[0] == 'servicenow':
            print('Existing Property Info:')
            print("\n")
            print("Value %s" % task.pythonScript.getProperty('servicenowServer'))
            print("\n")
            print("Type %s" % type(task.pythonScript.getProperty('servicenowServer')))
            print("\n")
            print("Get Type %s" % task.pythonScript.getProperty('servicenowServer').getType())
            print("\n")
            print("###")
            print("\n")
            print('Searched Property Info:')
            print("\n")
            print("Value %s" % servicenow_servers[0])
            print("\n")
            print("Type %s" % type(servicenow_servers[0]))
            print("\n")
            print("Get Type %s" % servicenow_servers[0].getType())
            print("\n")
            # This works
            #task.pythonScript.setProperty('servicenowServer', task.pythonScript.getProperty('servicenowServer'))
            #task.pythonScript.setProperty('servicenowServer', servicenow_servers[0])
            task.pythonScript.servicenowServer = servicenow_servers[0]
            print(task.getTaskType())
            print("\n")
            taskApi.updateTask(task)

And the output of that:

Existing Property Info:
Value Configuration/Custom/Configuration3dacad8ce8d14937957b960ec2f848a3
Type <type 'com.xebialabs.xlrelease.domain.configuration.HttpConnection'>
Get Type servicenow.Server

###

Searched Property Info:
Value Configuration/Custom/Configuration8b1ce7e06cb54b139c732e7396e5f845
Type <type 'instance'>
Get Type servicenow.Server

Exception during execution: AttributeError: 'com.xebialabs.xlrelease.domain.PythonScript' object has no attribute 'servicenowServer' in <script> at line number 27

And if I uncomment the setProperty line, I get a different error:

Exception during execution: java.lang.ClassCastException: java.lang.ClassCastException in <script> at line number 30

HOWEVER COMMA

If I use the instance that’s provided, everything works fine. For example:

task.pythonScript.setProperty('servicenowServer', task.pythonScript.getProperty('servicenowServer'))

So I went to the source

There should be a Property called ‘tablename’ in this Task Type, but when I call it, I get:

Exception during execution: AttributeError: 'com.xebialabs.xlrelease.domain.PythonScript' object has no attribute 'tablename' in <script> at line number 28

This error is thrown for all of the Properties that should be there. So for some reason, I can’t use task.pythonScript.$property to access different properties.

FWIW, the documentation did specify that it extended xlrelease.PythonScript, and not com.xebialabs.xlrelease.domain.PythonScript if that makes a difference.

I need to solve one of my two problems:

  1. task.pythonScript.$property doesn’t retrieve the custom servicenow.Task properties (as defined in the link above)
  2. .setProperty() won’t work when the value that is being set is coming from the configurationApi.

EDIT

Here is the json of one of my tasks:

                {
                    "attachments": [],
                    "checkAttributes": false,
                    "comments": [],
                    "container": "Applications/Folder943a7b3816ea41e0b1cb4e4995efdac4/Release4e96350c5e65449285c032a1fe80e6ee/Phasef9eb72eec9ef454fb603d29b7193d738",
                    "delayDuringBlackout": false,
                    "dueSoonNotified": false,
                    "facets": [],
                    "failuresCount": 0,
                    "flagStatus": "OK",
                    "hasBeenDelayed": false,
                    "hasBeenFlagged": false,
                    "id": "Applications/Folder943a7b3816ea41e0b1cb4e4995efdac4/Release4e96350c5e65449285c032a1fe80e6ee/Phasef9eb72eec9ef454fb603d29b7193d738/Task5b82974578b349f69bf603e03fd2455b",
                    "keepPreviousOutputPropertiesOnRetry": false,
                    "locked": false,
                    "overdueNotified": false,
                    "postponedDueToBlackout": false,
                    "pythonScript": {
                        "checkForStatus": "Closed Complete",
                        "customScriptTask": "Applications/Folder943a7b3816ea41e0b1cb4e4995efdac4/Release4e96350c5e65449285c032a1fe80e6ee/Phasef9eb72eec9ef454fb603d29b7193d738/Task5b82974578b349f69bf603e03
fd2455b",
                        "data": {},
                        "id": "Applications/Folder943a7b3816ea41e0b1cb4e4995efdac4/Release4e96350c5e65449285c032a1fe80e6ee/Phasef9eb72eec9ef454fb603d29b7193d738/Task5b82974578b349f69bf603e03fd2455b/Python
Script",
                        "servicenowServer": "Configuration/Custom/ServiceNow Prod",
                        "statusField": "state",
                        "sysId": "94a498af1bdcc810597a1fc58d4bcb8f",
                        "tableName": "change_task",
                        "type": "servicenow.PollingCheckStatus",
                        "username": "redacted"
                    },
                    "status": "PLANNED",
                    "tags": [],
                    "taskFailureHandlerEnabled": false,
                    "taskRecoverOp": "RUN_SCRIPT",
                    "title": "Check CTASK Status",
                    "type": "xlrelease.CustomScriptTask",
                    "variableMapping": {
                        "pythonScript.password": "${global.redacted}"
                    },
                    "waitForScheduledStartDate": true,
                    "watchers": []
                }

Sorry for the novella, but I wanted to document what I was running into on this.

#7

Hi smacz,
Sorry for the late reply. I tried this snippet in my personal XLR 9.0.2 instance and works fine. I am pulling up a future task and updating the server to a reference “snow 2”. The task that i am updating is of type servicenow.Create Change Task

t = taskApi.searchTasksByTitle(“mytask”,“dev”,release.id)[0]
snowlist = configurationApi.searchByTypeAndTitle(“servicenow.Server”,“snow 2”)
t.pythonScript.servicenowServer = snowlist[0]
taskApi.updateTask(t.id, t)

#8

Hi smacz,
So i tried your script and i accept that there is some unexpected classcastexception while you loop through the tasks. Now i made a couple of modifications.

  1. phase, task are keywords that you can use in the current task to refer to current task and current phase so changed the loops to refer to p, t

  2. the object task vs when you loop through phase.tasks probably has some variation and causing the classcastexception with setproperty for servicenowServer so i end up pulling the task again through get and that works fine

servicenow_servers = configurationApi.searchByTypeAndTitle("servicenow.Server", releaseVariables['servicenow_instance'])
print("\n")
for p in release.phases:
    for t in p.tasks:
        if str(t.getTaskType()).split('.')[0] == 'servicenow':
            temp_task = taskApi.getTask(t.id)
            print('Existing Property Info:')
            print("\n")
            print("Value %s" % temp_task.pythonScript.getProperty("servicenowServer"))
            print("\n")
            print("Type %s" % type(temp_task.pythonScript.getProperty("servicenowServer")))
            print("\n")
            print("###")
            print("\n")
            print('Searched Property Info:')
            print("\n")
            print("Value %s" % servicenow_servers[0])
            print("\n")
            print("Type %s" % type(servicenow_servers[0]))
            print("\n")
            print("Get Type %s" % servicenow_servers[0].getType())
            print("\n")
            # This works
            temp_task.pythonScript.setProperty("servicenowServer",servicenow_servers[0])
            print("\n")
            taskApi.updateTask(temp_task.id, temp_task)
#9

I have also updated this code snippet as a reference here https://github.com/xebialabs-community/xlr-jython-code-snippets/blob/master/README.md#dynamically-choose-a-target-server-for-all-tasks-of-that-type-in-a-release

#10

That worked! Thanks for the help and explanation.

Is there any write-up of reserved variable names in XLR?

#11

https://docs.xebialabs.com/jython-docs/#!/xl-release/9.0.x//service/XLReleaseApi
https://docs.xebialabs.com/v.9.0/xl-release/concept/variables-in-xl-release/#special-release-variables
you can also look at all the variables that are exposed in the context by doing print vars() or print globals().
when you do that, you will also have to open up some permissions in the script.policy file

when i try, it gives an error like this

Exception during execution: java.security.AccessControlException: java.security.AccessControlException: access denied ("java.io.FilePermission" "{ServerWorkingDirectory}/lib/jython-standalone-2.7.1.patch2618.jar/Lib/../LICENSE.txt" "read") in <script> at line number 1

you can then edit the XLR_HOME/conf/script.policy to add those permissions, restart and it can show you a lot more objects that are internally exposed.

Amit

1 Like