我有jenkins设置,现在我想将节点添加到jenkins,我正在按照How-to-Connect-to-Remote-SSH-Slaves中的步骤进行操作。
使用slave node
私钥创建凭证的步骤。我尝试使用ansible的jenkins api来创建它。
playbook中的任务是
- name: Read private key file content of slave1
slurp:
src: "{{ ansible_env.HOME }}/.ssh/slave1"
register: private_key_file
tags:
- credential
- name: Add credential to add node
uri:
body: |
json={
"": "0",
"credentials": {
"scope": "GLOBAL",
"id": "jenkins_linux_slave1_auth",
"username": "jenkins",
"password": "",
"privateKeySource": {
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource",
"privateKey": "{{ private_key_file['content'] | b64decode }}",
},
"description": "Jenkins Linux Slave1 Authentication",
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
}
}
force_basic_auth: yes
method: POST
password: "{{ jenkins_user_token }}"
status_code: 302
url: "{{ jenkins_url }}/credentials/store/system/domain/_/createCredentials"
user: "{{ jenkins_user }}"
validate_certs: no
tags:
- credential
但这失败了
$ ansible-playbook -i hosts jenkins_config.yaml --verbose -u root --ask-pass -b -e "jenkins_user=admin" -e "jenkins_user_token=admin" --tags credential
Using /root/ansible_playbooks/ansible.cfg as config file
SSH password:
PLAY [jenkins_servers] ***************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [jenkins_config : Read private key file content of slave1] **********************************************************************************************************************************************************************
ok: [localhost] => {"changed": false, "content": "Content", "encoding": "base64", "source": "/root/.ssh/slave1"}
TASK [jenkins_config : Add credential to add node] ***********************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"cache_control": "no-cache,no-store,must-revalidate", "changed": false, "connection": "close", "content": "\n\n\n\n\n \n <!DOCTYPE html><html><head resURL=\"/static/92560838\" data-rooturl=\"\" data-resurl=\"/static/92560838\">\n \n\n <title>Jenkins [Jenkins]</title><link rel=\"stylesheet\" href=\"/static/92560838/css/layout-common.css\" type=\"text/css\" /><link rel=\"stylesheet\" href=\"/static/92560838/css/style.css\" type=\"text/css\" /><link rel=\"stylesheet\" href=\"/static/92560838/css/color.css\" type=\"text/css\" /><link rel=\"stylesheet\" href=\"/static/92560838/css/responsive-grid.css\" type=\"text/css\" /><link rel=\"shortcut icon\" href=\"/static/92560838/favicon.ico\" type=\"image/vnd.microsoft.icon\" /><link color=\"black\" rel=\"mask-icon\" href=\"/images/mask-icon.svg\" /><script>var isRunAsTest=false; var rootURL=\"\"; var resURL=\"/static/92560838\";</script><script src=\"/static/92560838/scripts/prototype.js\" type=\"text/javascript\"></script><script src=\"/static/92560838/scripts/behavior.js\" type=\"text/javascript\"></script><script src='/adjuncts/92560838/org/kohsuke/stapler/bind.js' type='text/javascript'></script><script src=\"/static/92560838/scripts/yui/yahoo/yahoo-min.js\"></script><script src=\"/static/92560838/scripts/yui/dom/dom-min.js\"></script><script src=\"/static/92560838/scripts/yui/event/event-min.js\"></script><script src=\"/static/92560838/scripts/yui/animation/animation-min.js\"></script><script src=\"/static/92560838/scripts/yui/dragdrop/dragdrop-min.js\"></script><script src=\"/static/92560838/scripts/yui/container/container-min.js\"></script><script src=\"/static/92560838/scripts/yui/connection/connection-min.js\"></script>
"content_length": "27072", "content_type": "text/html;charset=utf-8", "date": "Mon, 22 Jan 2018 15:58:04 GMT", "expires": "Thu, 01 Jan 1970 00:00:00 GMT", "msg": "Status code was not [302]: HTTP Error 500: Server Error", "redirected": false, "server": "Jetty(9.4.z-SNAPSHOT)", "set_cookie": "JSESSIONID.8c551130=node0v7u4nqouxb1l1kcnd5139in7616.node0;Path=/;Secure;HttpOnly", "status": 500, "url": "http://localhost:8080/credentials/store/system/domain/_/createCredentials", "x_content_type_options": "nosniff", "x_frame_options": "sameorigin", "x_hudson": "1.395", "x_hudson_theme": "default", "x_instance_identity": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgORb1hlBOGx2LlN77veNlsGhwykedmrM+XqbHh0Fq4UGHQKhFicOXSPKiuOr4XpfWRZtYAy7jrY59cCF4So2qHionFUBjQespaALVC+aWQC3qIaZC4NlDgZXz+xQCFFrgW8G2iX2DA5kbPuwuIsv4WlgWvk8Z3kNmAxr16xhRq1R+RmdtVnmTaRyZiHdyQXdVpNHuYzITHfzUyIVIa8elbylS2CgDBMKRasxf7ewX++5Qp5rM5OzDbb5QLAueDhoyjAN2aA+jibUfYKoO7rwgpO3zMbIxuT9SKI7DMM7+TOEDQaH9SF0n+l/WXqpN6PLur9/o/10gsPghMXaV//KpQIDAQAB", "x_jenkins": "2.89.3", "x_jenkins_session": "92560838"}
to retry, use: --limit @/root/ansible_playbooks/jenkins_config.retry
PLAY RECAP ***************************************************************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=1
我检查了jenkins日志,它显示了json解析的错误。
Jan 22, 2018 11:02:17 AM org.eclipse.jetty.server.handler.ContextHandler$Context log
WARNING: Error while serving http://localhost:8080/credentials/store/system/domain/_/createCredentials
java.lang.reflect.InvocationTargetException
at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:347)
at org.kohsuke.stapler.interceptor.RequirePOST$Processor.invoke(RequirePOST.java:52)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: javax.servlet.ServletException: Failed to parse JSON:{
"": "0",
"credentials": {
"scope": "GLOBAL",
"id": "jenkins_linux_slave1_auth",
"username": "jenkins",
"password": "",
"privateKeySource": {
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource",
"privateKey": "-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
<MULTI LINE PRIVATE KEY>
-----END RSA PRIVATE KEY-----
",
},
"description": "Jenkins Linux Slave1 Authentication",
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
}
}
at org.kohsuke.stapler.RequestImpl.getSubmittedForm(RequestImpl.java:1021)
at com.cloudbees.plugins.credentials.CredentialsStoreAction$DomainWrapper.doCreateCredentials(CredentialsStoreAction.java:832)
at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:343)
... 84 more
Caused by: net.sf.json.JSONException: Unterminated string at character 365 of {
"": "0",
"credentials": {
"scope": "GLOBAL",
"id": "jenkins_linux_slave1_auth",
"username": "jenkins",
"password": "",
"privateKeySource": {
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource",
"privateKey": "-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
<MULTI LINE PRIVATE KEY>
-----END RSA PRIVATE KEY-----
",
},
"description": "Jenkins Linux Slave1 Authentication",
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
}
}
at net.sf.json.util.JSONTokener.syntaxError(JSONTokener.java:499)
at net.sf.json.util.JSONTokener.nextString(JSONTokener.java:237)
at net.sf.json.util.JSONTokener.nextValue(JSONTokener.java:345)
at net.sf.json.JSONObject._fromJSONTokener(JSONObject.java:955)
at net.sf.json.JSONObject.fromObject(JSONObject.java:156)
at net.sf.json.util.JSONTokener.nextValue(JSONTokener.java:348)
at net.sf.json.JSONObject._fromJSONTokener(JSONObject.java:955)
at net.sf.json.JSONObject.fromObject(JSONObject.java:156)
at net.sf.json.util.JSONTokener.nextValue(JSONTokener.java:348)
at net.sf.json.JSONObject._fromJSONTokener(JSONObject.java:955)
at net.sf.json.JSONObject._fromString(JSONObject.java:1145)
at net.sf.json.JSONObject.fromObject(JSONObject.java:162)
at net.sf.json.JSONObject.fromObject(JSONObject.java:132)
at org.kohsuke.stapler.RequestImpl.getSubmittedForm(RequestImpl.java:1019)
... 87 more
如果我将私有文件的内容手动复制到有效负载中的privateKey
,它可以正常工作。
复制文件内容与slurp['content]|b64decode
之间的区别是什么?
答案 0 :(得分:1)
privateKey
字段后面有一个多余的逗号,您需要删除它试试这个:
...
body: |
json={
"": "0",
"credentials": {
"scope": "GLOBAL",
"id": "jenkins_linux_slave1_auth",
"username": "jenkins",
"password": "",
"privateKeySource": {
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource",
"privateKey": {{ private_key_file['content'] | b64decode | tojson }}
},
"description": "Jenkins Linux Slave1 Authentication",
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
}
}
...
答案 1 :(得分:0)
我有同样的问题。
使用slurp获取私钥并传递值时,出现错误。
完成任务:
- name: Get private key vagrant
slurp:
src: '{{slave_linux_jenkins_private_key}}'
register: private_key_file
- name: Add credential to Node
uri:
url: "{{master_url}} / credentials / store / system / domain / _ / createCredentials"
user: "{{master_username}}"
password: "fooo"
method: POST
status_code: 302
force_basic_auth: true
body_format: json
body: |
json = {
"": "0",
"credentials": {
"scope": "GLOBAL",
"id": "{{slave_linux_jenkins_cred_id}}",
"username": "{{slave_linux_jenkins_username}}",
"password": "",
"privateKeySource": {
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey $ DirectEntryPrivateKeySource",
"privateKey": "{{private_key_file ['content'] | b64decode | replace ('\ n', '')}}"
},
"description": "Node app-protheus",
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
}
}
我通过以下方式进行测试:
"privateKey": "{{private_key_file ['content'] | b64decode | replace ('\ n', '')}}"
"privateKey": "{{private_key_file ['content'] | b64decode | to_json}}"
错误:
fatal: [protheus]: FAILED! => {"cache_control": "must-revalidate,no-cache,no-store", "changed": false, "connection": "close", "content": "html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/>\n<title>Error 400 Nothing is submitted</title>\n</head>\n<body><h2>HTTP ERROR 400 Nothing is submitted</h2>\n<table>\n<tr><th>URI:</th<td>/credentials/store/system/domain/_/createCredentials</td></tr>\n<tr><th>STATUS:</th><td>400</td></tr>\n<tr><th>MESSAGE:</th><td>Nothing is submitted</td></tr>\n<tr><th>SERVLET:</th><td>Stapler</td></tr>\n</table>\n<hr><a href=\"http://eclipse.org/jetty\">Powered by Jetty://9.4.27.v20200227</a><hr/>\n\n</body>\n</html>\n", "content_length": "527", "content_type": "text/html;charset=iso-8859-1", "elapsed": 1, "msg": "Status code was 400 and not [302]: HTTP Error 400: Bad Request", "redirected": false, "server":"Jetty(9.4.27.v20200227)", "status": 400, "url":"http://192.168.0.120:9080/credentials/store/system/domain/_/createCredentials", "x_content_type_options": "nosniff"}