renommage majuscules qd public et debut env service

This commit is contained in:
eleonore12345 2024-08-12 15:29:28 +02:00
parent bfc872dab8
commit 04e1e1b964
12 changed files with 151 additions and 103 deletions

View File

@ -5,9 +5,8 @@
#include <iostream> #include <iostream>
#include "BashManager.h" #include "BashManager.h"
int BashManager::execute(string command) int BashManager::Execute(string command)
{ {
cout << "command is " << command << endl;
FILE * p = popen(command.c_str(),"r"); FILE * p = popen(command.c_str(),"r");
if( p == NULL) if( p == NULL)
{ {
@ -18,7 +17,7 @@ int BashManager::execute(string command)
return 0; return 0;
} }
string BashManager::executeAndReadResult(string command) string BashManager::ExecuteAndReadResult(string command)
{ {
string result=""; string result="";
char lineBuffer [4095]={0}; //4095 is the maximum length of a shell line char lineBuffer [4095]={0}; //4095 is the maximum length of a shell line

View File

@ -12,8 +12,8 @@ using namespace std;
class BashManager class BashManager
{ {
public: public:
static string executeAndReadResult(string command); static string ExecuteAndReadResult(string command);
static int execute(string command); static int Execute(string command);
}; };
#endif #endif

View File

@ -116,12 +116,12 @@ int BashModule::executeScriptAs(string serviceUsername, string script)
} }
//public methods //public methods
int BashModule::prepare() int BashModule::Prepare()
{ {
return 0; return 0;
} }
int BashModule::deploy (string serviceUsername) int BashModule::Deploy (string serviceUsername)
{ {
string deployScript="./services/"+serviceUsername+"/deploy.sh"; //to be executed as current user string deployScript="./services/"+serviceUsername+"/deploy.sh"; //to be executed as current user
string deployAsScript="./services/"+serviceUsername+"/deploy_user.sh"; //to be executed as the user corresponding to the service string deployAsScript="./services/"+serviceUsername+"/deploy_user.sh"; //to be executed as the user corresponding to the service
@ -136,7 +136,7 @@ int BashModule::deploy (string serviceUsername)
} }
int BashModule::remove (string serviceUsername) int BashModule::Remove (string serviceUsername)
{ {
string removeScript="./services/"+serviceUsername+"/undeploy_user.sh"; string removeScript="./services/"+serviceUsername+"/undeploy_user.sh";
if (executeScript(serviceUsername,removeScript)!=0){ if (executeScript(serviceUsername,removeScript)!=0){
@ -146,7 +146,7 @@ int BashModule::remove (string serviceUsername)
return 0; return 0;
} }
int BashModule::clean() int BashModule::Clean()
{ {
return 0; return 0;
} }

View File

@ -12,10 +12,10 @@ class BashModule : public Module
public: public:
BashModule(); BashModule();
~BashModule(){} //inline ~BashModule(){} //inline
int prepare (); int Prepare ();
int deploy (string serviceUsername); int Deploy (string serviceUsername);
int remove(string serviceUsername); int Remove(string serviceUsername);
int clean (); int Clean ();
private: private:
int executeScript(string serviceUsername,string script); int executeScript(string serviceUsername,string script);
int executeScriptAs(string serviceUsername,string script); int executeScriptAs(string serviceUsername,string script);

View File

@ -11,43 +11,15 @@ DockerModule::DockerModule()
{ {
name="Docker"; name="Docker";
} }
//public methods
int DockerModule::prepare() //private methods
int DockerModule::removeContainersCreatedByDockerCompose()
{ {
return BashManager::execute("systemctl start docker docker.socket"); return BashManager::Execute("docker-compose down --rmi all --remove-orphans");
} }
int DockerModule::deploy (string serviceUsername) int DockerModule::removeContainersWithServiceName(string serviceName)
{
cout << "docker module deploy" << endl;
//test if there is a docker-compose.yml or docker-compose.yaml
string docker_compose="./services/"+serviceUsername+"/docker-compose.yml";
if(!(filesystem::exists(docker_compose))){
docker_compose="./services/"+serviceUsername+"/docker-compose.yaml";
if(!(filesystem::exists(docker_compose))){
cout << "No docker-compose for this service." << endl;
return 0;
}
}
//pulling images
int pulling =BashManager::execute("docker-compose pull")==0;
if(pulling==0){
//starting service
int starting=BashManager::execute("docker-compose up -d --remove-orphans");
}else{
cerr << "Error in "<< name << "deploying "<< serviceUsername << endl;
return -1;
}
return 0;
}
int removeContainersCreatedByDockerCompose()
{
return BashManager::execute("docker-compose down --rmi all --remove-orphans");
}
int removeContainersWithServiceName(string serviceName)
{ {
//constructing the name of the docker container from the name of the service by replacing . with _ //constructing the name of the docker container from the name of the service by replacing . with _
size_t pos=serviceName.find('.'); size_t pos=serviceName.find('.');
@ -62,11 +34,41 @@ int removeContainersWithServiceName(string serviceName)
[ -z \"$container\" ] && continue || true ; \ [ -z \"$container\" ] && continue || true ; \
docker rm \"$container\" ; \ docker rm \"$container\" ; \
done <<< \"$(docker ps | grep '" + dockerService + "' | cut -d ' ' -f 1)\""; done <<< \"$(docker ps | grep '" + dockerService + "' | cut -d ' ' -f 1)\"";
return BashManager::execute(cmd); return BashManager::Execute(cmd);
} }
} }
//public methods
int DockerModule::Prepare()
{
return BashManager::Execute("systemctl start docker docker.socket");
}
int DockerModule::remove (string serviceUsername) int DockerModule::Deploy (string serviceUsername)
{
cout << "docker module deploy" << endl;
//test if there is a docker-compose.yml or docker-compose.yaml
string docker_compose="./services/"+serviceUsername+"/docker-compose.yml";
if(!(filesystem::exists(docker_compose))){
docker_compose="./services/"+serviceUsername+"/docker-compose.yaml";
if(!(filesystem::exists(docker_compose))){
cout << "No docker-compose for this service." << endl;
return 0;
}
}
//pulling images
int pulling =BashManager::Execute("docker-compose pull")==0;
if(pulling==0){
//starting service
int starting=BashManager::Execute("docker-compose up -d --remove-orphans");
}else{
cerr << "Error in "<< name << "deploying "<< serviceUsername << endl;
return -1;
}
return 0;
}
int DockerModule::Remove (string serviceUsername)
{ {
//remove unwanted containers //remove unwanted containers
removeContainersCreatedByDockerCompose(); removeContainersCreatedByDockerCompose();
@ -74,7 +76,7 @@ int DockerModule::remove (string serviceUsername)
return 0; return 0;
} }
int DockerModule::clean() int DockerModule::Clean()
{ {
return 0; return 0;
} }

View File

@ -12,9 +12,12 @@ class DockerModule : public Module
public: public:
DockerModule();//inline DockerModule();//inline
~DockerModule(){} //inline ~DockerModule(){} //inline
int prepare (); int Prepare ();
int deploy (string serviceUsername); int Deploy (string serviceUsername);
int remove(string serviceUsername); int Remove(string serviceUsername);
int clean (); int Clean ();
private:
int removeContainersCreatedByDockerCompose();
int removeContainersWithServiceName (string serviceUsename);
}; };
#endif #endif

View File

@ -14,10 +14,10 @@ class Module
Module(){}; Module(){};
//=0 means pure virtual method, making Module a pure virtual class //=0 means pure virtual method, making Module a pure virtual class
virtual ~Module()=0; //make protected to ensure it is not used externally? virtual ~Module()=0; //make protected to ensure it is not used externally?
virtual int prepare ()=0; virtual int Prepare ()=0;
virtual int deploy (string serviceUsername)=0; virtual int Deploy (string serviceUsername)=0;
virtual int remove(string serviceUsername)=0; virtual int Remove(string serviceUsername)=0;
virtual int clean ()=0; virtual int Clean ()=0;
friend ostream & operator<< (ostream & out, const Module & m); friend ostream & operator<< (ostream & out, const Module & m);
string name; string name;
}; };

View File

@ -7,15 +7,15 @@
//constructor and destructor defined inline //constructor and destructor defined inline
//public methods //public methods
int Service::getUserID () const int Service::GetUserID () const
{ {
return userID; return userID;
} }
string Service::getUsername() const string Service::GetUsername() const
{ {
return username; return username;
} }
list<string> Service::getServers() const list<string> Service::GetServers() const
{ {
return servers; return servers;
} }
@ -23,7 +23,7 @@ list<string> Service::getServers() const
//operator == override //operator == override
bool Service::operator == (const Service & service) const bool Service::operator == (const Service & service) const
{ {
if (service.getServers()==servers && service.getUserID()==userID && service.getUsername()==username){ if (service.GetServers()==servers && service.GetUserID()==userID && service.GetUsername()==username){
return true; return true;
}else{ }else{
return false; return false;

View File

@ -15,9 +15,9 @@ class Service {
public: public:
Service(int aUserID, string aUsername, list <string> aServers):userID(aUserID),username(aUsername),servers(aServers){} Service(int aUserID, string aUsername, list <string> aServers):userID(aUserID),username(aUsername),servers(aServers){}
~Service(){} ~Service(){}
int getUserID () const; int GetUserID () const;
string getUsername() const; string GetUsername() const;
list<string> getServers() const; list<string> GetServers() const;
bool operator == (const Service & service) const; bool operator == (const Service & service) const;
friend ostream & operator<<(ostream & out, const Service & s); friend ostream & operator<<(ostream & out, const Service & s);
private: private:

View File

@ -8,49 +8,50 @@
#include <fstream> #include <fstream>
#include <string> #include <string>
#include "Services.h" #include "Services.h"
#include "BashManager.h"
//constructor //constructor
Services::Services(string ServicesCSV) Services::Services()
{ {
services=readServicesFromCSV(ServicesCSV); services=readServicesFromCSV();
} }
//destructor //destructor
Services::~Services(){} Services::~Services(){}
//public methods //public methods
vector<Service> Services::getServices()const vector<Service> Services::GetServices()const
{ {
return services; return services;
} }
const Service* Services::findByUsername(string aUsername) const const Service* Services::FindByUsername(string aUsername) const
{ {
//this method may disappear. Serves development purposes for now. //this method may disappear. Serves development purposes for now.
for (const Service & service : services){ for (const Service & service : services){
if (service.getUsername().compare(aUsername)==0){ if (service.GetUsername().compare(aUsername)==0){
return &service; return &service;
} }
} }
return nullptr; return nullptr;
} }
const Service * Services::findByID(int aUserID) const const Service * Services::FindByID(int aUserID) const
{ {
//this method may disappear. Serves development purposes for now. //this method may disappear. Serves development purposes for now.
for (const Service & service : services){ for (const Service & service : services){
if (service.getUserID()==aUserID){ if (service.GetUserID()==aUserID){
return &service; return &service;
} }
} }
return nullptr; return nullptr;
} }
list<const Service*> Services::findByServer(string aServer) const list<const Service*> Services::FindByServer(string aServer) const
{ {
//this method may disappear. Serves development purposes for now. //this method may disappear. Serves development purposes for now.
list<const Service*> result; list<const Service*> result;
for (const Service & service : services){ for (const Service & service : services){
for (string server : service.getServers()){ for (string server : service.GetServers()){
if(server.compare(aServer)==0){ if(server.compare(aServer)==0){
result.push_back(&service); result.push_back(&service);
} }
@ -60,17 +61,22 @@ list<const Service*> Services::findByServer(string aServer) const
} }
//private methods //private methods
vector <Service> Services::readServicesFromCSV (string CSV) const vector <Service> Services::readServicesFromCSV () const
{ {
//this method extracts the list of uid|username|servers from the services.csv file //this method extracts the list of uid|username|servers from the services.csv file
//and returns them in a vector <Service>, with Service a structure defined in the header
vector <Service> result; vector <Service> result;
char * CSV = getenv("servicefile"); //service file is an environment variable
// Check if the environment variable is set
if (CSV==nullptr) {
cerr << "Error when trying to read services.csv. Environment variable servicefiles is not set." << endl;
return result;
}
ifstream streamServices(CSV); ifstream streamServices(CSV);
if (!streamServices){ if (!streamServices){
cout << "Invalid services.csv file." << endl; cout << "Invalid services.csv file." << endl;
}else{ }else{
string line; string line;
string tmpUserID=""; //used before converting to int string tmpUserID; //used before converting to int
int userID; int userID;
string username; string username;
string server; string server;

View File

@ -18,14 +18,14 @@ class Services
//extracts the list of uid|username|service from the services.csv file //extracts the list of uid|username|service from the services.csv file
{ {
public: public:
Services(string servicesCSV="../src/services.csv"); Services();
vector<Service> getServices() const; vector<Service> GetServices() const;
const Service * findByUsername(string aUsername) const; const Service * FindByUsername(string aUsername) const;
const Service * findByID(int aUserID) const; const Service * FindByID(int aUserID) const;
list<const Service*> findByServer(string aServer) const; list<const Service*> FindByServer(string aServer) const;
~Services(); ~Services();
private: private:
vector <Service> readServicesFromCSV (string CSV) const; vector <Service> readServicesFromCSV () const;
vector <Service> services; vector <Service> services;
}; };
#endif #endif

View File

@ -24,7 +24,7 @@ int isServiceOnServer(string serviceUsername)
//it looks into the /etc/hosts file thanks to a pipe to a separate bash process //it looks into the /etc/hosts file thanks to a pipe to a separate bash process
{ {
string cmd ="getent hosts " +serviceUsername; string cmd ="getent hosts " +serviceUsername;
string result = BashManager::executeAndReadResult(cmd); string result = BashManager::ExecuteAndReadResult(cmd);
if(result.find("::1")!=string::npos){ //if result contains "::1" which is the notation for loopback in IpV6 if(result.find("::1")!=string::npos){ //if result contains "::1" which is the notation for loopback in IpV6
cout << "service on server" << endl; cout << "service on server" << endl;
return 0; return 0;
@ -39,19 +39,19 @@ int createUser(string serviceUsername)
//this method creates a Unix user dedicated to the service //this method creates a Unix user dedicated to the service
//get the User ID from servers.csv //get the User ID from servers.csv
int uidStart=2000; //so that the uids do not overlap with existing uids int uidStart=2000; //so that the uids do not overlap with existing uids
Services services = Services("./services/services.csv"); Services services = Services();
const Service * service = services.findByUsername(serviceUsername); const Service * service = services.FindByUsername(serviceUsername);
int uid = (*service).getUserID()+uidStart; int uid = (*service).GetUserID()+uidStart;
//test if user already exists //test if user already exists
string cmd = "id -u "+serviceUsername; string cmd = "id -u "+serviceUsername;
string res = BashManager::executeAndReadResult (cmd); string res = BashManager::ExecuteAndReadResult (cmd);
if(res==to_string(uid)){ if(res==to_string(uid)){
cout << "user already existed" << endl; cout << "user already existed" << endl;
return 0; return 0;
} }
//create user //create user
string cmd2 ="useradd -u " + to_string(uid) + " " + serviceUsername + "&& usermod -s /sbin/nologin "+ serviceUsername; //no direct login string cmd2 ="useradd -u " + to_string(uid) + " " + serviceUsername + "&& usermod -s /sbin/nologin "+ serviceUsername; //no direct login
string res2 = BashManager::executeAndReadResult(cmd2); string res2 = BashManager::ExecuteAndReadResult(cmd2);
if (res2 != ""){ if (res2 != ""){
cerr << "Error when executing the bash command to create a user specific to the service." << endl; cerr << "Error when executing the bash command to create a user specific to the service." << endl;
cerr << res2 << endl; cerr << res2 << endl;
@ -62,9 +62,23 @@ int createUser(string serviceUsername)
int createEnvService(string serviceUsername) int createEnvService(string serviceUsername)
{ {
Services services;
//create directories //create directories
//filesystem::create_directories() //filesystem::create_directories()
string http_dir="/srv/http/"+serviceUsername;
string data_dir="/data/"+serviceUsername;
string secret_dir="/data/secrets/"+serviceUsername;
string docker_dir="/services/"+serviceUsername;
string jc_service=serviceUsername;
string home="/data/"+serviceUsername;
string net="172.29."+services.FindByUsername(serviceUsername)->GetUserID();
/*
"HTTP_DIR='/srv/http/$service'" "$dir/.env"
cert="$(findcert.sh "$service")" || true
if [ -n "$cert" ] ; then
line_in_file "JC_CERT='$cert'" "$dir/.env"
fi*/
/* /*
run mkdir -p "$DATA_DIR" "$HTTP_DIR" run mkdir -p "$DATA_DIR" "$HTTP_DIR"
@ -86,29 +100,39 @@ int removeEnvService()
int createEnv() int createEnv()
{ {
//this method writes environment variables in a file and sets them for every bash call
string proxyDir="etc/nginx"; string proxyDir="etc/nginx";
string nginx_conf_path=proxyDir+"/sites-enabled";
string new_nginx_conf_path=proxyDir+"/new-sites-enabled";
string dns_certs_path="/data/dnscerts.jean-cloud.org/certs/live"; string dns_certs_path="/data/dnscerts.jean-cloud.org/certs/live";
string http_certs_path="/etc/letsencrypt/live"; string http_certs_path="/etc/letsencrypt/live";
string dummy_cert_path=http_certs_path+"/dummy";
string servicefile="./services/services.csv";
string services_uid_start="2000";
//create a file accessible outside the C++ program
ofstream outfile ("/etc/jeancloud.env"); ofstream outfile ("/etc/jeancloud.env");
outfile << "proxy_dir=" << proxyDir << endl; outfile << "proxy_dir=" << proxyDir << endl;
outfile << "nginx_conf_path=" << proxyDir << "/sites-enabled/" <<endl; outfile << "nginx_conf_path=" << nginx_conf_path << endl;
outfile << "new_nginx_conf_path=" << proxyDir << "/new-sites-enabled" << endl; outfile << "new_nginx_conf_path=" << new_nginx_conf_path << endl;
outfile << "dns_certs_path=" << dns_certs_path << endl; outfile << "dns_certs_path=" << dns_certs_path << endl;
outfile << "http_certs_path=" << http_certs_path << endl; outfile << "http_certs_path=" << http_certs_path << endl;
outfile << "dummy_cert_path=" << http_certs_path << "/dummy" <<endl; outfile << "dummy_cert_path=" << dummy_cert_path << endl;
outfile << "servicefile=/services/services.csv"; outfile << "servicefile=" << servicefile << endl;
outfile << "services_uid_start=2000" << endl; outfile << "services_uid_start=" << services_uid_start << endl;
outfile.close(); outfile.close();
return 0;
}
int deployAll() //setting the environment variables for all the shell commands called in this C++ programm
{ setenv("proxy_dir",proxyDir.c_str(),1);
//this method deploys all the services that are on this server setenv("nginx_conf_path",nginx_conf_path.c_str(),1);
cout << "deploying all" <<endl; setenv("new_nginx_conf_path",new_nginx_conf_path.c_str(),1);
createEnv(); setenv("dns_certs_path",dns_certs_path.c_str(),1);
//for each service deploy service setenv("http_certs_path",http_certs_path.c_str(),1);
setenv("dummy_cert_path",dummy_cert_path.c_str(),1);
setenv("servicefile",servicefile.c_str(),1);
setenv("services_uid_start",services_uid_start.c_str(),1);
return 0; return 0;
} }
@ -126,7 +150,7 @@ int deployService(string serviceUsername){
//call to the deploy functionality of all modules //call to the deploy functionality of all modules
//the modules themselves determine their course of action depending on the service //the modules themselves determine their course of action depending on the service
for(Module * mod_ptr : modules){ for(Module * mod_ptr : modules){
int modResult = (*mod_ptr).deploy(serviceUsername); int modResult = (*mod_ptr).Deploy(serviceUsername);
if (modResult!=0){ if (modResult!=0){
cerr << "Error in " << (*mod_ptr) << " when deploying " << serviceUsername << endl; cerr << "Error in " << (*mod_ptr) << " when deploying " << serviceUsername << endl;
} }
@ -138,6 +162,20 @@ int deployService(string serviceUsername){
return 0; return 0;
} }
int deployAll()
{
//this method deploys all the services that are on this server
cout << "deploying all" <<endl;
createEnv();
//initializing modules
Services services = Services();
for (Service service : services.GetServices()){
deployService(service.GetUsername());
}
//for each service deploy service
return 0;
}
int removeAll() int removeAll()
{ {
cout << "removing all"<<endl; cout << "removing all"<<endl;