Files
KubeControl/src/kubecontrol/KubePod.cpp

415 lines
11 KiB
C++

#include "curlpp/Options.hpp"
#include "kubecontrol/PodController.hpp"
#include "kubecontrol/Utils.hpp"
#include "nlohmann/json_fwd.hpp"
#include "yaml-cpp/binary.h"
#include <cctype>
#include <exception>
#include <fstream>
#include <future>
#include <iterator>
#include <kubecontrol/KubePod.hpp>
#include <memory>
#include <sstream>
#include <string>
#include <thread>
#include <filesystem>
#include "loguru.hpp"
#include "yaml-cpp/node/node.h"
namespace kubecontrol
{
KubePod::KubePod(std::string Owner, std::string Uuid, std::string ContainerImage,std::string Namespace)
:Owner_(Utils::to_lower(Owner)),
Uuid_(Utils::to_lower(Uuid)),
Namespace_(Namespace),
EnvirmonentVars_()
{
ContainerRegistry_ = "kmaster.ti.unibw-hamburg.de:30808";
EnvirmonentVars_ = std::map<std::string, std::string>();
this->PathToYaml_ = "config/pods/" + this->Uuid_ + ".yaml";
if( std::filesystem::directory_entry("config").exists() != true)
{
std::filesystem::create_directory("config");
}
std::filesystem::directory_entry entry("config/pods");
if(entry.exists() != true)
{
std::filesystem::create_directory("config/pods");
}
addContainer(Uuid, ContainerImage);
}
KubePod::KubePod(std::string Owner, std::string Uuid, std::string Component, std::string ContainerImage,std::string Namespace):
Owner_(Utils::to_lower(Owner)),
Uuid_(Utils::to_lower(Uuid)),
Component_(Utils::to_lower(Component)),
Namespace_(Namespace),
EnvirmonentVars_()
{
ContainerRegistry_ = "kmaster.ti.unibw-hamburg.de:30808";
EnvirmonentVars_ = std::map<std::string, std::string>();
this->PathToYaml_ = "config/pods/" + this->Uuid_ + ".yaml";
if( std::filesystem::directory_entry("config").exists() != true)
{
std::filesystem::create_directory("config");
}
std::filesystem::directory_entry entry("config/pods");
if(entry.exists() != true)
{
std::filesystem::create_directory("config/pods");
}
addContainer(Uuid, ContainerImage);
}
void KubePod::addContainer(std::string name,std::string image, std::shared_ptr<std::map<std::string, std::string>> envs, PullPolicy pullPolicy )
{
YAML::Node container;
transform(image.begin(), image.end(), image.begin(), ::tolower);
transform(name.begin(), name.end(), name.begin(), ::tolower);
container["name"] = name+"-container";
container["image"] = this->ContainerRegistry_ + "/" + image;
container["imagePullPolicy"] = toString(pullPolicy);
if (envs != nullptr)
{
int i = 0;
for(auto [key,value] : *envs)
{
container["env"][i]["name"] = key;
container["env"][i]["value"] = value;
i++;
}
}
ContainerImages_.push_back(container);
}
std::string KubePod::getUUID()
{
return this->Uuid_;
}
std::string KubePod::getOwner()
{
return this->Owner_;
}
std::string KubePod::getIp()
{
return this->Ip_;
}
std::string KubePod::getStatus()
{
return this->Status_;
}
void KubePod::setEnvironmentVar(std::string key, std::string val)
{
EnvirmonentVars_.emplace(key,val);
}
std::map<std::string, std::string> KubePod::GetEnvironmentVars()
{
return EnvirmonentVars_;
}
std::string KubePod::GetEnvironmentVar(std::string key)
{
if(EnvirmonentVars_.contains(key)) {
return EnvirmonentVars_[key];
} else {
return nullptr;
}
}
void KubePod::setArgs(std::string args)
{
Args_.emplace_back(Utils::to_lower(args));
}
std::vector<std::string> KubePod::GetArgs()
{
return Args_;
}
void KubePod::setCommand(std::string command)
{
PodCommand_ = Utils::to_lower(command);
}
std::string KubePod::getCommand()
{
return PodCommand_;
}
void KubePod::setComponent(std::string component)
{
this->Component_ = Utils::to_lower(component);
}
std::string KubePod::getComponent()
{
return this->Component_;
}
void KubePod::setName(std::string name)
{
this->Name_ = name;
}
std::string KubePod::getName()
{
return this->Name_;
}
std::string KubePod::createYAML()
{
YAML::Node node;
node["apiVersion"] = "v1";
node["kind"] = "Pod";
node["metadata"]["name"] = this->Uuid_;
node["metadata"]["namespace"] = this->Namespace_;
node["metadata"]["labels"]["app.kubernetes.io/name"] = this->Uuid_;
node["metadata"]["labels"]["app.kubernetes.io/part-of"] = this->Owner_;
// if (!std::empty(this->Component_)) node["metadata"]["labels"]["app.kubernetes.io/component"] = this->Component_;
node["metadata"]["labels"]["app.kubernetes.io/component"] = this->Component_;
for (int i = 0; i< this->ContainerImages_.size(); i++)
{
node["spec"]["containers"][i] = this->ContainerImages_[i];
// node["spec"]["containers"][i]["name"] = this->Uuid_+"-container";
// node["spec"]["containers"][i]["image"] = this->ContainerRegistry_ + "/" + this->ContainerImages_[i];
// node["spec"]["containers"][i]["imagePullPolicy"] = imagePullPolicy;
// node["spec"]["containers"][i]["ports"][0]["containerPort"] = 10000;
// node["spec"]["containers"][i]["ports"][0]["protocol"] = "UDP";
}
int i = 0;
for (auto item :EnvirmonentVars_) {
node["spec"]["containers"][0]["env"][i]["name"] = item.first;
node["spec"]["containers"][0]["env"][i]["value"] = item.second;
i++;
}
if (Args_.size() > 0)
{
node["spec"]["containers"][0]["args"].SetStyle(YAML::EmitterStyle::Flow);
for (auto item : Args_) {
node["spec"]["containers"][0]["args"].push_back(item);
}
}
if (!PodCommand_.empty())
{
node["spec"]["containers"][0]["command"].SetStyle(YAML::EmitterStyle::Flow);
node["spec"]["containers"][0]["command"].push_back(PodCommand_);
}
node["spec"]["terminationGracePeriodSeconds"] = 5;
node["spec"]["restartPolicy"] = "Never";
YAMLNode_ = node;
std::ofstream fout(this->PathToYaml_);
fout << node;
fout.close();
return this->PathToYaml_;
}
int KubePod::start(KubernetesAPI APIInterface,bool WaitTillRunning)
{
std::string request = "/api/v1/namespaces/simulator/pods/";
this->createYAML();
std::stringstream stream;
stream << YAMLNode_;
std::string response = APIInterface.performRequest(request,"POST",stream.str());
extractInformationFromResopnse(response);
auto timeoutTime = std::chrono::system_clock::now() + std::chrono::seconds(10);
if (WaitTillRunning == true ) {
while ((this->Status_ != "Running" && this->Status_ != "Succeeded") || std::chrono::system_clock::now() >= timeoutTime) {
// LOG_S(INFO)<<"wainting till running " << this->Status_;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
this->updateInfoForThisPod(APIInterface);
}
}
else {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
return 0;
}
int KubePod::stop(KubernetesAPI APIInterface)
{
std::string request = "/api/v1/namespaces/simulator/pods/"+Uuid_;
std::string result = APIInterface.performRequest(request,"DELETE");
LOG_S(INFO)<<"stopping: " <<Uuid_;
return 0;
}
int KubePod::stopChilds(KubernetesAPI APIInterface)
{
auto uuids = this->getPodsChilds(APIInterface);
if (uuids.size() == 0)
{
return 1;
}
for(auto i: uuids)
{
std::string request = "/api/v1/namespaces/simulator/pods/"+i.UUID;
std::string result = APIInterface.performRequest(request,"DELETE");
}
return 0;
}
int KubePod::updateInfoForThisPod(KubernetesAPI APIInterface)
{
std::string request = "/api/v1/namespaces/simulator/pods/"+Uuid_+"/status";
std::string result = APIInterface.performRequest(request,"GET");
if (result == "")
{
return 1;
}
if (extractInformationFromResopnse(result)!= 0)
{
return 1;
}
return 0;
}
std::vector<PodChild> KubePod::getPodsChilds( KubernetesAPI APIInterface)
{
std::string request = "/api/v1/namespaces/simulator/pods?labelSelector=app.kubernetes.io/part-of="+Uuid_;
std::string result = APIInterface.performRequest(request,"GET");
if (result == "")
{
return std::vector<PodChild>();
}
extractInformationFromResopnse(result);
return this->ChildPods;
}
int KubePod::extractInformationFromResopnse(std::string response)
{
if (response == "")
{
return 1 ;
}
// LOG_S(INFO)<< response;
nlohmann::json j;
try {
j = nlohmann::json::parse(response);
if(j.contains("kind") && j["kind"] == "Pod")
{
if( j["status"].contains("podIP")) this->Ip_ = j["status"]["podIP"].get<std::string>();
this->Status_ = j["status"]["phase"].get<std::string>();
this->PartOf_ = j["metadata"]["labels"]["app.kubernetes.io/part-of"];
}else if(j.contains("items") && j["items"].is_array())
{
for (auto i : j["items"])
{
// LOG_S(INFO)<<i;
PodChild child;
child.UUID =i["metadata"]["name"].get<std::string>();
child.IP = i["status"]["podIP"].get<std::string>();
child.Status = i["status"]["phase"].get<std::string>();
child.Component = i["metadata"]["labels"]["app.kubernetes.io/component"].get<std::string>();
this->ChildPods.push_back(child);
}
}else{
return 1;
}
} catch (const std::exception e) {
LOG_S(ERROR)<< "Exeption in extractInformationFromResopnse() :" << e.what();
std::exception_ptr p = std::current_exception();
LOG_S(ERROR)<< "Exeption :" << p.__cxa_exception_type()->name();
LOG_S(INFO)<<j;
return 1;
}
return 0;
}
}