У меня есть настройка jenkins, теперь я хочу добавить узел в jenkins, я выполняю шаги в Как подключиться к удаленным SSH-подчиненным.
Шаг для создания учетных данных с slave node
закрытый ключ. Я пытаюсь создать это, используя 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
?
Я считаю, что ваш JSON недействителен после того, как он был расширен механизмом шаблонов. Строки в файлах JSON не могут содержать символы новой строки, а строка личного ключа содержит символы новой строки. Вы можете проверить свой JSON с помощью такого инструмента, как JSONLint.
использовать sed -e 's/\n/\\n/g' privkey.rsa
чтобы изменить свой приватный ключ, и он будет проанализирован