Closed piyush94 closed 3 years ago
Got it, it's available with object $DEPLOY_ID
.
Is it possible to know if the current deployment failed or succeeded in the DMScript. We are running a Post Action on Application deployment, and would like to trigger a webhook if deployment is successful.
Here is how the stack works - https://docs.deployhub.com/userguide/dmscript/dmscript-stack/
Let me check on the exit code for the deployment step. I need to see when the exit code is pushed into the stack.
Thanks.
I guess if the deployment has failed then the Post Action will not run anyway. Is that right?
Is the action being run at the Component Level a custom action, ie Helm Deployment? Or is this for file based deployments?
Yes, I believe the Post Action is skipped. Need to double check.
It’s a Post Action associated with the Application. It executes a DMScript procedure.
You should be able to use $? to check the exit code of the previous task. I double checked the code and looks like the Application Post Task will get run even after a failure for a component deployment. I need to setup a test scenario to verify.
In my testing environment, Post Action did not run if any associated component deployment failed in the application.
One issue I found in JSON parsing from the REST API response, DMScript is unable to parse decimal numbers,
{
"_class": "jenkins.metrics.impl.TimeInQueueAction",
"blockedDurationMillis": 0,
"blockedTimeMillis": 0,
"buildableDurationMillis": 0,
"buildableTimeMillis": 0,
"buildingDurationMillis": 0,
"executingTimeMillis": 0,
"executorUtilization": 1.0, <-- HERE
"subTaskCount": 0,
"waitingDurationMillis": 5763,
"waitingTimeMillis": 5763
}
Error:
syntax error, unexpected '.', expecting ',' or '}'
I tried using to_json
https://docs.deployhub.com/userguide/dmscript/dmscript-tojson/, but it did not help.
@piyush94 we will need to convert the 1.0 to a string. DMScript does not support floating point numbers. This update should enable the json to be parsed correctly.
Here is the fix for the json error docker pull quay.io/deployhub/deployhub-pro:ui-skin-v9.0.0.3136-g35c342d
.
Can you please send a copy of the log when the deployment fails? We need to look at the DMScript stack trace if there is one.
Stack when a component deployment fails.
Exception at line 0: Custom Action helm_install_action for Component helm_test_comp_01 Failed: Return Code: 1
--
Stacktrace:
server sb-helm client
dropzone 1
deploy
component helm_test_comp_01
application helm_test_app
avloop
application helm_test_app
environment ustr-rancher-sb
global
This is achieving the result of not executing the Application Post Action. Let me know your thoughts. There might be cases where execution of the rest of the tasks is needed. If the background is ansible, maybe ignore_errors can be used.
Here is the fix for the json error
docker pull quay.io/deployhub/deployhub-pro:ui-skin-v9.0.0.3136-g35c342d
.Can you please send a copy of the log when the deployment fails? We need to look at the DMScript stack trace if there is one.
When using this image I faced two issues.
failed to login with LDAP
.Runtime error at line 34: Failed to load plugin "restful"
I had upgraded from version, master-v9.0.0.2953-g34c693f
I tested the wrong image by accident. Let me re-test deployhub-pro:ui-skin-v9.0.0.3136-g35c342d.
The helm custom action can be modified to catch the bad return code and set a global DMScript exitcode that we can then check from the Application Post Action. The Application Post Action would do the restapi call you need and then exit with non-zero to cause the deployment to fail. Note: we can make this optional at the Helm custom action level so by default acts as is.
Here is the corrected image ta for both the base and the reverse proxy: ui-skin-v9.0.0.3138-g3af5090
@sbtaylor15 I tried the image, but still facing authentication issue when deploying.
Trying basic bind uid=sohalpiy,dc=uis,dc=unisys,dc=com
Thu May 20 06:52:12 2021: LDAP Login Exception caught - returning [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090453, comment: AcceptSecurityContext error, data 52e, v3839]
Thu May 20 06:52:12 2021: ApiException caught e=Login failed
Thu May 20 06:52:12 2021: {"success":false,"error":"Login failed"}
UI login works fine.
Also facing issue with below DMScript procedure. It gets stuck at restful_post.
echo "Application : ${application.name}";
echo "Environment : ${environment.name}";
echo "Deployment exit code: $?";
set DEPLOY_ID = "7713";
echo "Deployment ID: $DEPLOY_ID";
set jenkins_server = "https://my.jenkins-server.com";
if ($DO_PUBLISH = "true") {
echo "Publishing DeployHub Manifest....";
echo "Product Style : ${PUBLISH_STYLE}";
echo "Version : ${PUBLISH_VERSION}";
echo "Push Manifest Group ID: ${PUSH_MANIFEST_GID}";
set params = "product=${PUBLISH_STYLE}&deployhubId=$DEPLOY_ID&version=${PUBLISH_VERSION}&pushManifestGroupID=${PUSH_MANIFEST_GID}";
echo "Params : ${params}";
set job_url = "${jenkins_server}/job/my_example_job/";
set cred = getcredential("GLOBAL.my_domain.jenkins-test");
set res = restful_get("${jenkins_server}/crumbIssuer/api/json", $cred, "cookiejar");
echo "Crumb res: ${res}";
set cookies = "JSESSIONID=${cookiejar.JSESSIONID}";
echo "Cookie jar : ${cookies}";
set headers={ "Jenkins-Crumb": "${res.crumb}", "Authorization": "Basic ${cred.b64auth}", "Accept": "*/*" };
set curr_req = "api/json";
set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null);
set build_number = "${job_status_res.nextBuildNumber}";
echo "Build number : ${build_number}";
set curr_req = "buildWithParameters";
echo "Build URL: $job_url$curr_req?$params";
// procedure getting stuck here, not proceeding after this
set res = restful_post("$job_url$curr_req?$params", $cookies, $headers, null);
sleep(delay: 1);
set curr_req = "api/json";
set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null);
sleep(delay: 5);
while("${job_status_res.inQueue}" = true) {
echo "In queue...";
sleep(delay: 1);
set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null);
}
set curr_req = "${build_number}/api/json";
set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null);
while("${job_status_res.building}" = true) {
echo "Publishing...";
sleep(delay: 2);
set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null);
}
sleep(delay: 2);
set curr_req = "${build_number}/api/json";
set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null);
echo "Publish result : ${job_status_res.result}";
} else {
echo "DO_PUBLISH is false. Skipping publishing...";
}
@sbtaylor15 I tried the image, but still facing authentication issue when deploying.
Trying basic bind uid=sohalpiy,dc=uis,dc=unisys,dc=com Thu May 20 06:52:12 2021: LDAP Login Exception caught - returning [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090453, comment: AcceptSecurityContext error, data 52e, v3839] Thu May 20 06:52:12 2021: ApiException caught e=Login failed Thu May 20 06:52:12 2021: {"success":false,"error":"Login failed"}
UI login works fine.
Where is the deployment being started from, Jenkins or a curl call?
Also facing issue with below DMScript procedure. It gets stuck at restful_post.
echo "Application : ${application.name}"; echo "Environment : ${environment.name}"; echo "Deployment exit code: $?"; set DEPLOY_ID = "7713"; echo "Deployment ID: $DEPLOY_ID"; set jenkins_server = "https://my.jenkins-server.com"; if ($DO_PUBLISH = "true") { echo "Publishing DeployHub Manifest...."; echo "Product Style : ${PUBLISH_STYLE}"; echo "Version : ${PUBLISH_VERSION}"; echo "Push Manifest Group ID: ${PUSH_MANIFEST_GID}"; set params = "product=${PUBLISH_STYLE}&deployhubId=$DEPLOY_ID&version=${PUBLISH_VERSION}&pushManifestGroupID=${PUSH_MANIFEST_GID}"; echo "Params : ${params}"; set job_url = "${jenkins_server}/job/my_example_job/"; set cred = getcredential("GLOBAL.my_domain.jenkins-test"); set res = restful_get("${jenkins_server}/crumbIssuer/api/json", $cred, "cookiejar"); echo "Crumb res: ${res}"; set cookies = "JSESSIONID=${cookiejar.JSESSIONID}"; echo "Cookie jar : ${cookies}"; set headers={ "Jenkins-Crumb": "${res.crumb}", "Authorization": "Basic ${cred.b64auth}", "Accept": "*/*" }; set curr_req = "api/json"; set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null); set build_number = "${job_status_res.nextBuildNumber}"; echo "Build number : ${build_number}"; set curr_req = "buildWithParameters"; echo "Build URL: $job_url$curr_req?$params"; // procedure getting stuck here, not proceeding after this set res = restful_post("$job_url$curr_req?$params", $cookies, $headers, null); sleep(delay: 1); set curr_req = "api/json"; set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null); sleep(delay: 5); while("${job_status_res.inQueue}" = true) { echo "In queue..."; sleep(delay: 1); set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null); } set curr_req = "${build_number}/api/json"; set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null); while("${job_status_res.building}" = true) { echo "Publishing..."; sleep(delay: 2); set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null); } sleep(delay: 2); set curr_req = "${build_number}/api/json"; set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null); echo "Publish result : ${job_status_res.result}"; } else { echo "DO_PUBLISH is false. Skipping publishing..."; }
Is the restful_post returning a json string? If so, is it the json string have the float in it?
@sbtaylor15 I tried the image, but still facing authentication issue when deploying.
Trying basic bind uid=sohalpiy,dc=uis,dc=unisys,dc=com Thu May 20 06:52:12 2021: LDAP Login Exception caught - returning [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090453, comment: AcceptSecurityContext error, data 52e, v3839] Thu May 20 06:52:12 2021: ApiException caught e=Login failed Thu May 20 06:52:12 2021: {"success":false,"error":"Login failed"}
UI login works fine.
Where is the deployment being started from, Jenkins or a curl call?
I am starting the deployment from UI.
Also facing issue with below DMScript procedure. It gets stuck at restful_post.
echo "Application : ${application.name}"; echo "Environment : ${environment.name}"; echo "Deployment exit code: $?"; set DEPLOY_ID = "7713"; echo "Deployment ID: $DEPLOY_ID"; set jenkins_server = "https://my.jenkins-server.com"; if ($DO_PUBLISH = "true") { echo "Publishing DeployHub Manifest...."; echo "Product Style : ${PUBLISH_STYLE}"; echo "Version : ${PUBLISH_VERSION}"; echo "Push Manifest Group ID: ${PUSH_MANIFEST_GID}"; set params = "product=${PUBLISH_STYLE}&deployhubId=$DEPLOY_ID&version=${PUBLISH_VERSION}&pushManifestGroupID=${PUSH_MANIFEST_GID}"; echo "Params : ${params}"; set job_url = "${jenkins_server}/job/my_example_job/"; set cred = getcredential("GLOBAL.my_domain.jenkins-test"); set res = restful_get("${jenkins_server}/crumbIssuer/api/json", $cred, "cookiejar"); echo "Crumb res: ${res}"; set cookies = "JSESSIONID=${cookiejar.JSESSIONID}"; echo "Cookie jar : ${cookies}"; set headers={ "Jenkins-Crumb": "${res.crumb}", "Authorization": "Basic ${cred.b64auth}", "Accept": "*/*" }; set curr_req = "api/json"; set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null); set build_number = "${job_status_res.nextBuildNumber}"; echo "Build number : ${build_number}"; set curr_req = "buildWithParameters"; echo "Build URL: $job_url$curr_req?$params"; // procedure getting stuck here, not proceeding after this set res = restful_post("$job_url$curr_req?$params", $cookies, $headers, null); sleep(delay: 1); set curr_req = "api/json"; set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null); sleep(delay: 5); while("${job_status_res.inQueue}" = true) { echo "In queue..."; sleep(delay: 1); set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null); } set curr_req = "${build_number}/api/json"; set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null); while("${job_status_res.building}" = true) { echo "Publishing..."; sleep(delay: 2); set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null); } sleep(delay: 2); set curr_req = "${build_number}/api/json"; set job_status_res = restful_get("$job_url$curr_req", $cookies, $headers, null); echo "Publish result : ${job_status_res.result}"; } else { echo "DO_PUBLISH is false. Skipping publishing..."; }
Is the restful_post returning a json string? If so, is it the json string have the float in it?
Unfortunately, it’s not returning anything. It just stays stuck.
Sorry, just mean is the expected data from the restful_post json and if so json with the float?
Sorry, just mean is the expected data from the restful_post json and if so json with the float?
For build and buildWithParameters REST call, Jenkins is not returning any body. Just status code 201.
Ok, I will test it with an empty body being returned.
@piyush94 - We did something similar but in Python and then just passed in the attributes TOML file in (like the Helm Action). It was a bit easier to interact with Jenkins thru the Python library. Let me know if you want to go the Python route or stick with DMScript.
#!/usr/bin/python3
import subprocess
import sys
import time
import jenkins
import qtoml
def runcmd(cmd):
print(cmd)
lines = subprocess.run(cmd, check=False, shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE).stdout.decode('utf-8')
print(lines)
def main():
"""Main entry point <Chart Directory> <Override Values Toml>"""
newvals = {}
rspfile = sys.argv[1]
print("RSP=" + rspfile)
lines = subprocess.run(['cat', rspfile], check=False, stdout=subprocess.PIPE).stdout.decode('utf-8').split("\n")
# pprint(lines)
cleanvals = {}
for line in lines:
if ('=' in line):
key = line.split('=')[0]
value = line.split('=', 1)[-1].strip()
if (value.lower() == '"true"' or value.lower() == "'true'"):
value = "true"
if (value.lower() == '"false"' or value.lower() == "'false'"):
value = "false"
if ('?' not in key):
cleanvals[key] = value
valstr = ""
for key, value in cleanvals.items():
valstr = valstr + key + " = " + value + "\n"
values = qtoml.loads(valstr)
newvals.update(values)
component = newvals.get("component", "")
# now create jenkins job
jenkins_url = newvals.get("jenkins_url", "")
jenkins_user = newvals.get("jenkins_user", newvals.get('jenkinsuser', '')).strip()
jenkins_token = newvals.get("jenkins_token", newvals.get('jenkinspass', '')).strip()
jenkins_job = newvals.get("jenkins_init_repo_job", "")
server = jenkins.Jenkins(jenkins_url, username=jenkins_user, password=jenkins_token)
server.build_job(jenkins_job, {'REPO_NAME': component})
print('Running....')
while True:
if server.get_job_info(jenkins_job)['lastCompletedBuild']['number'] == server.get_job_info(jenkins_job)['lastBuild']['number']:
print("Build Number: " + str(server.get_job_info(jenkins_job)['lastCompletedBuild']['number']))
break
time.sleep(3)
print("Finished....\n")
console_output = server.get_build_console_output(jenkins_job, server.get_job_info(jenkins_job)['lastBuild']['number'])
print(console_output)
if __name__ == '__main__':
main()
@sbtaylor15 Thanks for the Python script. It's working as expected. So, will you be adding this as part of the DeployHub image or we can run it externally?
Edit: we can’t run externally as we want this action to be not dependent on the environment. It should run from inside DeployHub.
Also, some Generic attributes will be needed, such as creds["jenkins"], job_params, print_log (true, false), etc.
Will we be able to pass the job params dictionary from attributes? Maybe like job_params.param1=value1.
@piyush94 quay.io/deployhub/deployhub-pro:ui-skin-v9.0.0.3150-g4cd689a
has the fix for the LDAP deployment auth error and we added the dh2jenkins.py which is a generic Jenkins runner.
Parameters:
jenkins_url
jenkins_user or jenkinsuser
jenkins_token or jenkinspass
jenkins_job
jenkins_job_params.KEY1 = "VAL1"
jenkins_job_params.KEY2 = "VAL2"
jenkins_log (true or false to display log output)
creds['jenkins'] = 'jenkinsadmin' will pull the 'jenkinsadmin' credential and set the userid and password as jenkinsuser and jenkinspass
@sbtaylor15 if possible kindly share the Jenkins update in the old UI.
@piyush94 we pushed the JSON float fix and the dh2jenkins.py to the old ui.
main-v9.0.0.2954-g8c7a767
@sbtaylor15 Thanks. Do i need to add writeenv2toml procedure before running the jenkins script?
Correct, in the action put the WriteEnv2Toml procedure first and then the Jenkins one. The variable name will be $RspFile
@sbtaylor15 As I am running the Action as PostAction to an application, the server and component objects are empty. Hence due to the server object being empty dropzone is not getting created. And getting this error,
Creating Values TOML File
RspFile :
Runtime error at line 91: 'create' requires a dropzone to be specified
As you can see RspFIle is empty.
@piyush94 there is a method to create a dropzone object. Let us try that in the context of the PostAction and see if that fixes the error. Otherwise we will need to add a python script that will make a couple of rest calls to get the data and create the toml file.
@sbtaylor15 Could we see once if it would be easier to resolve the DMScript issue?
@piyush94 - you will need to specify the dropzone explicitly before trying to write the variables to the file.
echo "Creating Values TOML File";
echo "$DEPLOY_LOG";
using dropzone 'tdm_scripts_xxx' {
set creds = ${application.attributes['creds']};
foreach(cred: $creds)
{
set credname = ${creds[$cred]};
set c = getcredential($credname);
echo $cred + "user = \"" + ${c.username} + "\"";
echo $cred + "pass = \"" + ${c.password} + "\"";
}
set -g RspFile = ${dropzone.path} + "/values.toml";
echo $RspFile;
set d = now();
set sname = "s" + ${d.to_int()};
eval("using stream \$$sname;");
eval("set envstream = \$$sname;");
using stream $envstream {
echo "application = \"" + ${application.name} + "\"";
foreach(env: ${application.attributes}) {
echo $env + "= \"" + ${application.attributes[$env]} + "\"";
}
create(file: "values.toml", stream: $envstream);
}
}
using dropzone 'tdm_scripts_xxx' {
is the line needed (plus the }
at the end of the file). This will work for both pre and post actions to the Application.
@sbtaylor15 Thanks, this worked. The python-jenkins
module was missing from the image, but after installing it the specified job got triggered with parameters.
Traceback (most recent call last):
File "/opt/deployhub/engine/scripts/dh2jenkins.py", line 7, in
import jenkins
ModuleNotFoundError: No module named 'jenkins'
For jenkins_log
attribute, this is working for us.
if (jenkins_log):
print(console_output)
@piyush94 which image tag? I am seeing it installed already.
This one main-v9.0.0.2954-g8c7a767
Here is the updated image. quay.io/deployhub/deployhub-pro:main-v9.0.0.2955-g682117c
Hi @sbtaylor15 , Could you please update dh2jenkins with the attached file. This is having an update that allows anonymous users to trigger the Jenkins job. Thanks.
Added to the latest UI. Let me know if you need for the older one.
quay.io/deployhub/deployhub-pro:ui-skin-v9.0.0.3167-g0341de8
Yes, please add in the older one as well.
older ui updates
quay.io/deployhub/deployhub-pro:main-v9.0.0.2956-g908e48f
What all objects are available in the stack during deployment?
Is the current deployment id available?