Jenkins: configure slave node address dynamically using command or groovy script - ssh

I have kinda ssh slave build jenkins setup.
Jenkins server connect to Mac slave thru ssh. build ios apps there. two remote nodes are configured in Jenkins connected to the Mac.
The Mac has dhcp.
Every time my mac starts I want to run a script that tell the Jenkin server to configure the node's IP address pointing to the dhcp address that the mac receives. Since its dhcp it changes always.
Is possible to configure such? using shell script or perl ...
e.g. http://jenkins-server:8080/computer/mac-slave-enterprise/configure
is the node config url. If its possible to setup by sending host=10.1.2.100 & Submit=Save or something like this?
I found it is possible run Groovy script at
http://jenkins/script
or from mac command line or sh script,
$ curl -d "script=<your_script_here>" http://jenkins/script
I tried to get some info with this code but no luck, seems I have create SSLLauncher, but lost in how to grab a launcher things. There is no direct setHost or setLauncher thing.
following the tutorial at,
https://wiki.jenkins-ci.org/display/JENKINS/Display+Information+About+Nodes
but cannot set the host address.
println("node desc launcher = " + aSlave.getComputer().getLauncher());
//println("node desc launcher = " + aSlave.getComputer().getLauncher().setHost("10.11.51.70"));
println("node launcher host = " + aSlave.getComputer().getLauncher().getHost());
hudson.plugins.sshslaves.SSHLauncher ssl = aSlave.getComputer().getLauncher();
int port = ssl.getPort();
String userName, password, privateKey;
userName = ssl.getUsername();
password = ssl.getPassword();
privateKey = ssl.getPrivatekey();
println("user: "+userName + ", pwd: "+password + ", key: "+privateKey);
// all these values returns null.

Another way would be to just delete the node and recreate it.
Here is some groovy on how to delete it from here:
for (aSlave in hudson.model.Hudson.instance.slaves) {
if (aSlave.name == "MySlaveToDelete") {
println('====================');
println('Name: ' + aSlave.name);
println('Shutting down node!!!!');
aSlave.getComputer().setTemporarilyOffline(true,null);
aSlave.getComputer().doDoDelete();
}
And here is how to create one (source):
import jenkins.model.*
import hudson.model.*
import hudson.slaves.*
Jenkins.instance.addNode(new DumbSlave("test-script","test slave description","C:\\Jenkins","1",Node.Mode.NORMAL,"test-slave-label",new JNLPLauncher(),new RetentionStrategy.Always(),new LinkedList()))

Related

ftplib.error_perm: 550 Create directory operation failed while using FTP_TLS

I am trying to connect to a secure FTP server created based on this link. I have not followed step 8 in the link. I am able to establish the connection and also change and print directories but am unable to create new directories. I am also unable to fetch files list.
Here is my code snippet:
import ssl
from ftplib import FTP_TLS
import sys
import os
import os.path
def connect():
ftp = FTP_TLS()
ftp.debugging = 2
ftp.connect('ipaddress', 21)
ftp.set_pasv(False)
ftp.login('user', 'passwd')
return ftp
ftps = connect()
destdir = "/"
try:
resp = ftps.pwd()
ftps.cwd(destdir)
except Exception:
ftps.mkd(destdir)
print(resp)
root = 'C:\\Users\\****\\****\\Logs' # local dir
for (dir, _, files) in os.walk(root):
newdir = destdir+dir[len(root):len(dir)].replace("\\", "/")
print(newdir)
try:
ftps.cwd(newdir)
except Exception:
ftps.mkd(newdir)
I am using python 3.7.3 and the corresponding ftplib. I would be happy to provide any other details required.
PS: I am able to connect with Filezilla and create directories.
This is the error after running.
I am able to create the directories successfully once I change the dir to /logs. I am getting an error "ftplib.error_perm: 500 Illegal PORT command." whenever I send cmd like retrlines or storbinary
, I get this error
I have searched about this and people have asked to set it to pasv mode. When I do that, I get this error. FYI, I have enabled pasv mode in the config file
I tried changing the port number to a number between pasv ports enabled in the config file (between 30000-31000). It does not connect also in this case. Error returned "ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it"
I am working the first time with an FTP server or for that matter any server communications, so my problems might seem trivial. I am sorry for your trouble.
Thanks.

How to declare a variable and reuse it in icinga2 hosts section?

For now I use the below config for Icinga2 host server to work:
vars.health_check["my_module1"]={
host = "HEALTH_CHECK_SERVER_URL"
module = "my_module1"
}
vars.health_check["my_module2"]={
host = "HEALTH_CHECK_SERVER_URL"
module = "my_module2"
}
The problem as you see is that I have to redeclare the same host address. When I put the host address outside of service like below, it does not work and reloading of Icinga2 fails:
end_url = "HEALTH_CHECK_SERVER_URL"
vars.health_check["my_module1"]={
host = "$end_url$"
module = "my_module1"
}
vars.health_check["my_module2"]={
host = "$end_url$"
module = "my_module2"
}
I even tried to use vars.end_url but again the same scenario. How should I declare a variable in Icinga2.
You can use the host's address with $address$ so if the host's address is the what the URL resolves to it should work like:
end_url = "HEALTH_CHECK_SERVER_URL"
vars.health_check["my_module1"]={
host = "$address$"
module = "my_module1"
}
vars.health_check["my_module2"]={
host = "$address$"
module = "my_module2"
}
Have you looked into Icinga2 Director?. It's handy and host configs are more easily managed. Also, monitoring-portal.org Is a good resource for the Icinga Community.
If you use director you can make a clone of the command and then set the arguments to variables like $end_url$ then create the field. Then you can add the field to your template(import) and enter it once there.
For example we use this method for SNMP Community strings. We have a field for $snmp_community$ attached to our templates. So in any command where we need the community we just use this variable. This is how Icinga2 knows all our LAN Distro's community strings, and if we need to change it we just change it once.

Creating user in Jenkins via API

I was wondering if I can create a new user in Jenkins using its API. I can create jobs but the API docs for Jenkins don't have anything related to user creation.
Actually, I have to create a new user followed by creating a new job for that user, all of this using an API.
You're right, there is no explicit CLI command for adding a user. But you could use groovy script for this (using the CLI for execution).
The details depend on how your Jenkins is configured.
For example, if your Jenkins uses its own user database, then you could add a new user by the following CLI call:
echo 'jenkins.model.Jenkins.instance.securityRealm.createAccount("user1", "password123")' |
java -jar jenkins-cli.jar -s http://localhost/ groovy =
This shell command will create a new user with login "user1" and password "password123".
Here echo feeds a line of groovy code to a Jenkins CLI (note that = means that CLI should receive code from STDIN).
Also groovy script allows to manage user permissions, however, the exact code depends on what authorization strategy is used. You could use this sample script as a start.
This is how to create user after installation:
echo 'jenkins.model.Jenkins.instance.securityRealm.createAccount("user", "password")' | java -jar jenkins-cli.jar -auth admin:c3a5dcd6bc3f45ee8d6c9f0f5abc14c0 -s http://localhost:8080/ groovy =
Where c3a5dcd6bc3f45ee8d6c9f0f5abc14c0 is automatically generated password present in log or in file (for ubuntu): /var/lib/jenkins/secrets/initialAdminPassword
echo and pipe didn't work on my Windows, so I ended up using a script file instead. It's also easier to add more logic in the script file. The script below will check existing user before adding a new user, and then set the user's email after account creation and give READ access using Matrix-based security. You can run it by saving the script into a file, say user-creation.groovy, and then run the following,
java -jar jenkins-cli.jar -s http://localhost/ groovy user-creation.groovy testUser testPassword testEmail#testEmail.com
import hudson.model.*
import hudson.security.*
import hudson.tasks.Mailer
def userId = args[0]
def password = args[1]
def email = args[2]
def instance = jenkins.model.Jenkins.instance
def existingUser = instance.securityRealm.allUsers.find {it.id == userId}
if (existingUser == null) {
def user = instance.securityRealm.createAccount(userId, password)
user.addProperty(new Mailer.UserProperty(email));
def strategy = (GlobalMatrixAuthorizationStrategy) instance.getAuthorizationStrategy()
strategy.add(Hudson.READ, userId)
instance.setAuthorizationStrategy(strategy)
instance.save()
}
I managed to get the following python snippet to create a user with ssh-key:
import json
import requests
def main():
data = {
'credentials': {
'scope': "GLOBAL",
'username': "jenkins",
'privateKeySource': {
'privateKey': "-----BEGIN RSA PRIVATE KEY-----\nX\n-----END RSA PRIVATE KEY-----",
'stapler-class': "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource"
},
'stapler-class': "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
}
}
payload = {
'json': json.dumps(data),
'Submit': "OK",
}
r = requests.post("http://%s:%d/credential-store/domain/_/createCredentials" % (HOSTNAME, 8080), data=payload)
if r.status_code != requests.codes.ok:
print r.text
It is sort of like a REST interface except that one has to know the internals of the code and the names of the classes that the objects are supposed to decode to.
I'm trying to configure jenkins from an ansible script (running externally to the jenkins server); since the java cli doesn't support creating the credentials the python snippet seems the way to go.
Building on #vitaleek's answer the following will grab the default admin credentials from the file and create a new user:
pass=`sudo cat /var/lib/jenkins/secrets/initialAdminPassword` && echo 'jenkins.model.Jenkins.instance.securityRealm.createAccount("user1", "password123")' | sudo java -jar jenkins-cli.jar -auth admin:$pass -s http://localhost:8080/ groovy =
If you're like me and you couldn't find the jenkins-cli.jar at first, that can be pulled from your Jenkins server as follows:
curl -O http://127.0.0.1:8080/jnlpJars/jenkins-cli.jar

Does Node Manager through WLST in Weblogic 10.3.4 call startWeblogic.cmd

I am using weblogic 10.3.4 and have a WLST script which does the following
1. Creates a Domain
2. Create JDBC
3. Start NodeManager
4. Connect to Nodemanager
5. And Deploy my App
Below are the relevant sections of my script
templatehome = domainhome + "/wlserver/common/templates/domains/wls.jar"
readTemplate(templatehome)
create('MyDomain', 'Domain')
cd('/Security/MyDomain/User/weblogic')
cmo.setName(domainuserid)
cmo.setUserPassword(domainpwd)
writeDomain(domainlocation + '/'+ domainname)
---Some other code related to JDBC
closeTemplate()
---- Updating setDomainEnv.cmd
f = open(domainlocation+ '/' + domainname +'/bin/setDomainEnv.cmd', "a+")
f.write("set CLASSPATH=%DOMAIN_HOME%\lib\javax.el-api-2.2.4.jar;%DOMAIN_HOME%\lib\com.sun.el_2.2.0.v201105051105-com.sun.el_2.2.0.v201105051105.jar;%CLASSPATH%")
f.close()
startNodeManager()
nmConnect(domainuserid, domainpwd, 'localhost', '5556', 'MyDomain','D:/MyLoc/Tools/Weblogic/user_projects/domains/MyDomain')
nmStart('AdminServer')
connect()
deploy('myapp','my-war-location')
Please note that i am updating the SetDomainEnv.cmd in the WLST code itself.
When i run this script the domain gets created, the node manager gets started and the application gets deployed.
But the Server start does not happen through startWEblogic.cmd and my updated SetDomainEnv.cmd is not called.
So the question is does NodeManager use startWEblogic.cmd to start a Server?
If yes then why is it not happening in my code?
Check StartScriptEnabled and StartScriptName properties in nodemanager.properties (ex: wlserver_10.3/common/nodemanager/nodemanager.properties)
StartScriptEnabled should be set to true and StartScriptName should be set to startWebLogic.cmd. By default these values are set, if they are not then please set them and restart nodemanager for the changes to take effect.
If the above fix doesn't work, then please update the question with the nodemanager.log content.
Reference : http://docs.oracle.com/cd/E24329_01/web.1211/e21050/java_nodemgr.htm#i1068413

how to syslog-ng to remote facility

i have a host running syslog-ng. it does all it's stuff locally fine (creating log files etc). however, i would like to forward ALL of it's logs to a remote machine - specifically to one facility on the remote machine (local4). i tried playing around with rewrite (set-facility) and templates within the destination (syntax errors) - but to no avail.
destination remote_server {
udp(\"172.18.192.8\" port (514));
udp(\"172.18.192.9\" port (514));
};
rewrite r_local4 {
set-facility(local4);
};
filter f_alllogs {
level (debug...emerg);
};
log {
source(local);
filter(f_alllogs);
rewrite(r_local4)
destination(remote_server);
};
AFAIK, currently it is not possible to modify the facility of a message in syslog-ng.
Is there a special reason you want to do it?