fixed plugin bug for spawning nodes in a TURN based environment

This commit is contained in:
2023-02-10 17:19:28 +00:00
parent c42bf002de
commit afe4105e3a
3 changed files with 557 additions and 532 deletions

View File

@@ -29,6 +29,7 @@ type Config struct {
GroupTrackContainersPath string GroupTrackContainersPath string
FRPServerPort string FRPServerPort string
BehindNAT string BehindNAT string
AnsibleConfig string
//NetworkInterface string //NetworkInterface string
//NetworkInterfaceIPV6Index int //NetworkInterfaceIPV6Index int
} }
@@ -127,6 +128,7 @@ func SetDefaults() error {
defaults["ServerPort"] = "8088" defaults["ServerPort"] = "8088"
defaults["FRPServerPort"] = "0" defaults["FRPServerPort"] = "0"
defaults["BehindNAT"] = "True" defaults["BehindNAT"] = "True"
defaults["AnsibleConfig"] = defaultPath + "p2p/ansible/ansible.cfg"
// Random name generator // Random name generator
hostname, err := os.Hostname() hostname, err := os.Hostname()
if err != nil { if err != nil {

View File

@@ -1,452 +1,464 @@
package plugin package plugin
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"git.sr.ht/~akilan1999/p2p-rendering-computation/client" "git.sr.ht/~akilan1999/p2p-rendering-computation/client"
"git.sr.ht/~akilan1999/p2p-rendering-computation/config" "git.sr.ht/~akilan1999/p2p-rendering-computation/config"
"github.com/google/uuid" "github.com/google/uuid"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
"io/ioutil" "io/ioutil"
"os" "net"
"strconv" "os"
"text/template" "strconv"
"text/template"
"github.com/apenella/go-ansible/pkg/execute" "github.com/apenella/go-ansible/pkg/execute"
"github.com/apenella/go-ansible/pkg/options" "github.com/apenella/go-ansible/pkg/options"
"github.com/apenella/go-ansible/pkg/playbook" "github.com/apenella/go-ansible/pkg/playbook"
"github.com/apenella/go-ansible/pkg/stdoutcallback/results" "github.com/apenella/go-ansible/pkg/stdoutcallback/results"
"github.com/otiai10/copy" "github.com/otiai10/copy"
) )
// Plugins Array of all plugins detected // Plugins Array of all plugins detected
type Plugins struct { type Plugins struct {
PluginsDetected []*Plugin PluginsDetected []*Plugin
} }
// Plugin Information about the plugins available // Plugin Information about the plugins available
type Plugin struct { type Plugin struct {
FolderName string FolderName string
PluginDescription string PluginDescription string
path string path string
Execute []*ExecuteIP Execute []*ExecuteIP
NumOfPorts int NumOfPorts int
} }
// ExecuteIP IP Address to execute Ansible instruction // ExecuteIP IP Address to execute Ansible instruction
type ExecuteIP struct { type ExecuteIP struct {
ContainerID string ContainerID string
IPAddress string IPAddress string
SSHPortNo string SSHPortNo string
Success bool Success bool
} }
// Host Struct for ansible host // Host Struct for ansible host
// Generated from https://zhwt.github.io/yaml-to-go/ // Generated from https://zhwt.github.io/yaml-to-go/
type Host struct { type Host struct {
All struct { All struct {
Vars struct { Vars struct {
AnsiblePythonInterpreter string `yaml:"ansible_python_interpreter"` AnsiblePythonInterpreter string `yaml:"ansible_python_interpreter"`
} `yaml:"vars"` } `yaml:"vars"`
} `yaml:"all"` } `yaml:"all"`
Main struct { Main struct {
Hosts struct { Hosts struct {
Host1 struct { Host1 struct {
AnsibleHost string `yaml:"ansible_host"` AnsibleHost string `yaml:"ansible_host"`
AnsiblePort int `yaml:"ansible_port"` AnsiblePort int `yaml:"ansible_port"`
AnsibleUser string `yaml:"ansible_user"` AnsibleUser string `yaml:"ansible_user"`
AnsibleSSHPass string `yaml:"ansible_ssh_pass"` AnsibleSSHPass string `yaml:"ansible_ssh_pass"`
AnsibleSudoPass string `yaml:"ansible_sudo_pass"` AnsibleSudoPass string `yaml:"ansible_sudo_pass"`
} `yaml:"host1"` } `yaml:"host1"`
} `yaml:"hosts"` } `yaml:"hosts"`
} `yaml:"main"` } `yaml:"main"`
} }
// DetectPlugins Detects all the plugins available // DetectPlugins Detects all the plugins available
func DetectPlugins()(*Plugins,error){ func DetectPlugins() (*Plugins, error) {
config, err:= config.ConfigInit() config, err := config.ConfigInit()
if err != nil { if err != nil {
return nil,err return nil, err
} }
folders, err := ioutil.ReadDir(config.PluginPath) folders, err := ioutil.ReadDir(config.PluginPath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var plugins *Plugins = new(Plugins) var plugins *Plugins = new(Plugins)
for _, f := range folders { for _, f := range folders {
if f.IsDir() { if f.IsDir() {
//Declare variable plugin of type Plugin //Declare variable plugin of type Plugin
var plugin Plugin var plugin Plugin
// Setting name of folder to plugin // Setting name of folder to plugin
plugin.FolderName = f.Name() plugin.FolderName = f.Name()
// Getting Description from file description.txt // Getting Description from file description.txt
Description, err := ioutil.ReadFile(config.PluginPath + "/" + plugin.FolderName + "/description.txt") Description, err := ioutil.ReadFile(config.PluginPath + "/" + plugin.FolderName + "/description.txt")
// if we os.Open returns an error then handle it // if we os.Open returns an error then handle it
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Get Description from description.txt // Get Description from description.txt
plugin.PluginDescription = string(Description) plugin.PluginDescription = string(Description)
// Set plugin path // Set plugin path
plugin.path = config.PluginPath + "/" + plugin.FolderName plugin.path = config.PluginPath + "/" + plugin.FolderName
plugins.PluginsDetected = append(plugins.PluginsDetected, &plugin) plugins.PluginsDetected = append(plugins.PluginsDetected, &plugin)
// Get the number of ports the plugin needs // Get the number of ports the plugin needs
err = plugin.NumPorts() err = plugin.NumPorts()
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
} }
return plugins,nil return plugins, nil
} }
// SearchPlugin Detects plugin information based on the // SearchPlugin Detects plugin information based on the
// name provided on the parameter // name provided on the parameter
func SearchPlugin(pluginname string) (*Plugin,error) { func SearchPlugin(pluginname string) (*Plugin, error) {
plugins, err := DetectPlugins() plugins, err := DetectPlugins()
if err != nil { if err != nil {
return nil, err return nil, err
} }
// loop ot find the plugin name that matches // loop ot find the plugin name that matches
for _, plugin := range plugins.PluginsDetected { for _, plugin := range plugins.PluginsDetected {
if pluginname == plugin.FolderName { if pluginname == plugin.FolderName {
return plugin, nil return plugin, nil
} }
} }
return nil, errors.New("plugin not detected") return nil, errors.New("plugin not detected")
} }
// RunPlugin Executes plugins based on the plugin name provided // RunPlugin Executes plugins based on the plugin name provided
func RunPlugin(pluginName string ,IPAddresses []*ExecuteIP) (*Plugin,error) { func RunPlugin(pluginName string, IPAddresses []*ExecuteIP) (*Plugin, error) {
plugins, err := DetectPlugins() plugins, err := DetectPlugins()
if err != nil { if err != nil {
return nil,err return nil, err
} }
// Variable to store struct information about the plugin // Variable to store struct information about the plugin
var plugindetected *Plugin var plugindetected *Plugin
for _,plugin := range plugins.PluginsDetected { for _, plugin := range plugins.PluginsDetected {
if plugin.FolderName == pluginName { if plugin.FolderName == pluginName {
plugindetected = plugin plugindetected = plugin
plugindetected.Execute = IPAddresses plugindetected.Execute = IPAddresses
// Get Execute plugin path from config file // Get Execute plugin path from config file
config, err := config.ConfigInit() config, err := config.ConfigInit()
if err != nil { if err != nil {
return nil, err return nil, err
} }
plugindetected.path = config.PluginPath plugindetected.path = config.PluginPath
break break
} }
} }
if plugindetected == nil { if plugindetected == nil {
return nil, errors.New("Plugin not detected") return nil, errors.New("Plugin not detected")
} }
// Create copy of the plugin the tmp directory
// To ensure we execute the plugin from there
err = plugindetected.CopyToTmpPlugin()
if err != nil {
return nil, err
}
// Executing the plugin // Create copy of the plugin the tmp directory
err = plugindetected.ExecutePlugin() // To ensure we execute the plugin from there
if err != nil { err = plugindetected.CopyToTmpPlugin()
return nil,err if err != nil {
} return nil, err
}
return plugindetected,nil // Executing the plugin
err = plugindetected.ExecutePlugin()
if err != nil {
return nil, err
}
return plugindetected, nil
} }
// ExecutePlugin Function to execute plugins that are called // ExecutePlugin Function to execute plugins that are called
func (p *Plugin) ExecutePlugin() error { func (p *Plugin) ExecutePlugin() error {
// Run ip address to execute ansible inside // Run ip address to execute ansible inside
for _,execute := range p.Execute { for _, execute := range p.Execute {
// Modify ansible hosts before executing // Modify ansible hosts before executing
err := execute.ModifyHost(p) err := execute.ModifyHost(p)
if err != nil { if err != nil {
return err return err
} }
// sets the ports to the plugin folder // sets the ports to the plugin folder
err = p.AutoSetPorts(execute.ContainerID) err = p.AutoSetPorts(execute.ContainerID)
if err != nil { if err != nil {
return err return err
} }
err = execute.RunAnsible(p) err = execute.RunAnsible(p)
if err != nil { if err != nil {
return err return err
} }
// If ran successfully then change success flag to true // If ran successfully then change success flag to true
execute.Success = true execute.Success = true
} }
return nil return nil
} }
// RunAnsible Executes based on credentials on the struct // RunAnsible Executes based on credentials on the struct
func (e *ExecuteIP)RunAnsible(p *Plugin) error { func (e *ExecuteIP) RunAnsible(p *Plugin) error {
ansiblePlaybookConnectionOptions := &options.AnsibleConnectionOptions{ ansiblePlaybookConnectionOptions := &options.AnsibleConnectionOptions{
User: "master", User: "master",
} }
ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{
Inventory: p.path + "/" + p.FolderName + "/hosts", Inventory: p.path + "/" + p.FolderName + "/hosts",
ExtraVars: map[string]interface{}{"host_key_checking":"false"}, ExtraVars: map[string]interface{}{"ansible_ssh_common_args": "-o StrictHostKeyChecking=no"},
} }
ansiblePlaybookPrivilegeEscalationOptions := &options.AnsiblePrivilegeEscalationOptions{ ansiblePlaybookPrivilegeEscalationOptions := &options.AnsiblePrivilegeEscalationOptions{
Become: true, Become: true,
} }
playbook := &playbook.AnsiblePlaybookCmd{ playbook := &playbook.AnsiblePlaybookCmd{
Playbooks: []string{p.path + "/" + p.FolderName + "/site.yml"}, Playbooks: []string{p.path + "/" + p.FolderName + "/site.yml"},
ConnectionOptions: ansiblePlaybookConnectionOptions, ConnectionOptions: ansiblePlaybookConnectionOptions,
PrivilegeEscalationOptions: ansiblePlaybookPrivilegeEscalationOptions, PrivilegeEscalationOptions: ansiblePlaybookPrivilegeEscalationOptions,
Options: ansiblePlaybookOptions, Options: ansiblePlaybookOptions,
Exec: execute.NewDefaultExecute( Exec: execute.NewDefaultExecute(
execute.WithTransformers( execute.WithTransformers(
results.Prepend("success"), results.Prepend("success"),
), ),
), ),
} }
err := playbook.Run(context.TODO()) err := playbook.Run(context.TODO())
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
// ModifyHost adds IP address , port no to the config file // ModifyHost adds IP address , port no to the config file
func (e *ExecuteIP)ModifyHost(p *Plugin) error { func (e *ExecuteIP) ModifyHost(p *Plugin) error {
host,err := ReadHost(p.path + "/" + p.FolderName + "/hosts") host, err := ReadHost(p.path + "/" + p.FolderName + "/hosts")
if err != nil { if err != nil {
return err return err
} }
// Setting ansible host // Setting ansible host
host.Main.Hosts.Host1.AnsibleHost = e.IPAddress host.Main.Hosts.Host1.AnsibleHost = e.IPAddress
// Setting SSH port no // Setting SSH port no
host.Main.Hosts.Host1.AnsiblePort, err = strconv.Atoi(e.SSHPortNo) host.Main.Hosts.Host1.AnsiblePort, err = strconv.Atoi(e.SSHPortNo)
if err != nil { if err != nil {
return err return err
} }
// Setting SSH user name // Setting SSH user name
host.Main.Hosts.Host1.AnsibleUser = "master" host.Main.Hosts.Host1.AnsibleUser = "master"
// Setting SSH password // Setting SSH password
host.Main.Hosts.Host1.AnsibleSSHPass = "password" host.Main.Hosts.Host1.AnsibleSSHPass = "password"
// Setting SSH sudo password // Setting SSH sudo password
host.Main.Hosts.Host1.AnsibleSudoPass = "password" host.Main.Hosts.Host1.AnsibleSudoPass = "password"
// write modified information to the hosts yaml file // write modified information to the hosts yaml file
data,err := yaml.Marshal(host) data, err := yaml.Marshal(host)
if err != nil { if err != nil {
return err return err
} }
err = ioutil.WriteFile(p.path + "/" + p.FolderName + "/hosts",data,0777) err = ioutil.WriteFile(p.path+"/"+p.FolderName+"/hosts", data, 0777)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
// ReadHost Reads host file and adds // ReadHost Reads host file and adds
func ReadHost(filename string) (*Host, error) { func ReadHost(filename string) (*Host, error) {
buf, err := ioutil.ReadFile(filename) buf, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
c := &Host{} c := &Host{}
err = yaml.Unmarshal(buf, c) err = yaml.Unmarshal(buf, c)
if err != nil { if err != nil {
return nil, fmt.Errorf("in file %q: %v", filename, err) return nil, fmt.Errorf("in file %q: %v", filename, err)
} }
return c, nil return c, nil
} }
// RunPluginContainer Runs ansible plugin based on plugin name and container name which // RunPluginContainer Runs ansible plugin based on plugin name and container name which
// is derived from the tracked containers file // is derived from the tracked containers file
// We pass in the group ID as a parameter because when we modify the ports taken // We pass in the group ID as a parameter because when we modify the ports taken
func RunPluginContainer(PluginName string, ContainerID string) error { func RunPluginContainer(PluginName string, ContainerID string) error {
// Gets container information based on container ID // Gets container information based on container ID
ContainerInformation, err := client.GetContainerInformation(ContainerID) ContainerInformation, err := client.GetContainerInformation(ContainerID)
if err != nil { if err != nil {
return err return err
} }
// Setting Up IP's for which the plugins will be executed // Setting Up IP's for which the plugins will be executed
var ExecuteIPs []*ExecuteIP var ExecuteIPs []*ExecuteIP
var ExecuteIP ExecuteIP var ExecuteIP ExecuteIP
// Getting port no of SSH port // Getting port no of SSH port
for _,port := range ContainerInformation.Container.Ports.PortSet { for _, port := range ContainerInformation.Container.Ports.PortSet {
if port.PortName == "SSH" { if port.PortName == "SSH" {
ExecuteIP.SSHPortNo = fmt.Sprint(port.ExternalPort) ExecuteIP.SSHPortNo = fmt.Sprint(port.ExternalPort)
break break
} }
} }
// Handle error if SSH port is not provided // Handle error if SSH port is not provided
if ExecuteIP.SSHPortNo == "" { if ExecuteIP.SSHPortNo == "" {
return errors.New("SSH port not found") return errors.New("SSH port not found")
} }
// IP address of the container // Split the port no from ip address since current the IP address
ExecuteIP.IPAddress = ContainerInformation.IpAddress // field is populated as
// Set container ID to ExecutorIP // <ip address>:<port no>
ExecuteIP.ContainerID = ContainerInformation.Id
host, _, err := net.SplitHostPort(ContainerInformation.IpAddress)
if err != nil {
return err
}
// IP address of the container
ExecuteIP.IPAddress = host
// Set container ID to ExecutorIP
ExecuteIP.ContainerID = ContainerInformation.Id
// Append IP to list of executor IP // Append IP to list of executor IP
ExecuteIPs = append(ExecuteIPs, &ExecuteIP) ExecuteIPs = append(ExecuteIPs, &ExecuteIP)
// Run plugin to execute plugin // Run plugin to execute plugin
_, err = RunPlugin(PluginName,ExecuteIPs) _, err = RunPlugin(PluginName, ExecuteIPs)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
// CheckRunPlugin Checks if the ID belongs to the group or container // CheckRunPlugin Checks if the ID belongs to the group or container
// calls the plugin function the appropriate amount of times // calls the plugin function the appropriate amount of times
func CheckRunPlugin(PluginName string, ID string) error { func CheckRunPlugin(PluginName string, ID string) error {
// Check if the ID belongs to the group or container ID // Check if the ID belongs to the group or container ID
id, err := client.CheckID(ID) id, err := client.CheckID(ID)
if err != nil { if err != nil {
return err return err
} }
// When the ID belongs to a group // When the ID belongs to a group
if id == "group" { if id == "group" {
// gets the group information // gets the group information
group, err := client.GetGroup(ID) group, err := client.GetGroup(ID)
if err != nil { if err != nil {
return err return err
} }
// Iterate through each container information in the group // Iterate through each container information in the group
// and run the plugin in each of them // and run the plugin in each of them
for _, container := range group.TrackContainerList { for _, container := range group.TrackContainerList {
// runs plugin for each container // runs plugin for each container
err := RunPluginContainer(PluginName, container.Id) err := RunPluginContainer(PluginName, container.Id)
if err != nil { if err != nil {
return err return err
} }
} }
} else { // This means the following ID is a container ID } else { // This means the following ID is a container ID
err := RunPluginContainer(PluginName, ID) err := RunPluginContainer(PluginName, ID)
if err != nil { if err != nil {
return err return err
} }
} }
return nil return nil
} }
// CopyToTmpPlugin This function would ensure that we create a copy of the // CopyToTmpPlugin This function would ensure that we create a copy of the
// plugin in the tmp directory, and it would be executed // plugin in the tmp directory, and it would be executed
// from there. This due to the reason of automating port allocation // from there. This due to the reason of automating port allocation
// when running plugins // when running plugins
func (p *Plugin)CopyToTmpPlugin() error { func (p *Plugin) CopyToTmpPlugin() error {
// generate rand to UUID this is debug the ansible file if needed // generate rand to UUID this is debug the ansible file if needed
id := uuid.New() id := uuid.New()
// copies the plugin to the tmp directory // copies the plugin to the tmp directory
err := copy.Copy(p.path+"/"+p.FolderName, "/tmp/"+ id.String() + "_" + p.FolderName) err := copy.Copy(p.path+"/"+p.FolderName, "/tmp/"+id.String()+"_"+p.FolderName)
if err != nil { if err != nil {
return err return err
} }
// Set the plugin execution to the tmp location // Set the plugin execution to the tmp location
p.path = "/tmp" p.path = "/tmp"
p.FolderName = id.String() + "_" + p.FolderName p.FolderName = id.String() + "_" + p.FolderName
return nil return nil
} }
// AutoSetPorts Automatically maps free ports to site.yml file // AutoSetPorts Automatically maps free ports to site.yml file
func (p *Plugin)AutoSetPorts(containerID string) error { func (p *Plugin) AutoSetPorts(containerID string) error {
container , err := client.GetContainerInformation(containerID) container, err := client.GetContainerInformation(containerID)
if err != nil { if err != nil {
return err return err
} }
// variable that would have a list of ports // variable that would have a list of ports
// to be allocated to the plugin system // to be allocated to the plugin system
var ports []int var ports []int
// Counted that increments when a port is taken // Counted that increments when a port is taken
PortTaken := 0 PortTaken := 0
// setting all external ports available in an array // setting all external ports available in an array
for i, port := range container.Container.Ports.PortSet { for i, port := range container.Container.Ports.PortSet {
if port.IsUsed == false { if port.IsUsed == false {
// Ensuring we break outside the loop once the ports // Ensuring we break outside the loop once the ports
// are set. // are set.
if PortTaken >= p.NumOfPorts { if PortTaken >= p.NumOfPorts {
break break
} }
// Setting the following port flag to true // Setting the following port flag to true
container.Container.Ports.PortSet[i].IsUsed = true container.Container.Ports.PortSet[i].IsUsed = true
// Incrementing the variable PortTaken // Incrementing the variable PortTaken
PortTaken++ PortTaken++
ports = append(ports, port.ExternalPort) // Maps to internal since
} // Inside the machine
} // internal port -> (maps) same internal port
// TURN (i.e FRP) based approach (internal port -> maps to different external port)
ports = append(ports, port.InternalPort)
}
}
// parses the site.yml file in the tmp directory // parses the site.yml file in the tmp directory
t, err := template.ParseFiles(p.path + "/" + p.FolderName + "/site.yml") t, err := template.ParseFiles(p.path + "/" + p.FolderName + "/site.yml")
if err != nil { if err != nil {
return err return err
} }
// opens the output file // opens the output file
f, err := os.Create(p.path + "/" + p.FolderName + "/site.yml") f, err := os.Create(p.path + "/" + p.FolderName + "/site.yml")
if err != nil { if err != nil {
return err return err
} }
// sends the ports to the site.yml file to populate them // sends the ports to the site.yml file to populate them
err = t.Execute(f,ports) err = t.Execute(f, ports)
if err != nil { if err != nil {
return err return err
} }
// Once the following is done set port to taken // Once the following is done set port to taken
// n tracked container list // n tracked container list
err = container.ModifyContainerInformation() err = container.ModifyContainerInformation()
if err != nil { if err != nil {
return err return err
} }
// Once the following is done set port to taken // Once the following is done set port to taken
// I(Groups) // I(Groups)
err = container.ModifyContainerGroups() err = container.ModifyContainerGroups()
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
// NumPorts Gets the Number the ports the // NumPorts Gets the Number the ports the
// plugin requires // plugin requires
func (p *Plugin)NumPorts() error { func (p *Plugin) NumPorts() error {
jsonFile, err := os.Open(p.path + "/ports.json") jsonFile, err := os.Open(p.path + "/ports.json")
// if we os.Open returns an error then handle it // if we os.Open returns an error then handle it
if err != nil { if err != nil {
return err return err
} }
// defer the closing of our jsonFile so that we can parse it later on // defer the closing of our jsonFile so that we can parse it later on
defer jsonFile.Close() defer jsonFile.Close()
// read our opened xmlFile as a byte array. // read our opened xmlFile as a byte array.
byteValue, _ := ioutil.ReadAll(jsonFile) byteValue, _ := ioutil.ReadAll(jsonFile)
// we unmarshal our byteArray which contains our // we unmarshal our byteArray which contains our
// jsonFile's content into 'users' which we defined above // jsonFile's content into 'users' which we defined above
json.Unmarshal(byteValue, &p) json.Unmarshal(byteValue, &p)
return nil return nil
} }

View File

@@ -1,246 +1,257 @@
package plugin package plugin
import ( import (
"fmt" "fmt"
"git.sr.ht/~akilan1999/p2p-rendering-computation/client" "git.sr.ht/~akilan1999/p2p-rendering-computation/client"
"git.sr.ht/~akilan1999/p2p-rendering-computation/config" "git.sr.ht/~akilan1999/p2p-rendering-computation/config"
"git.sr.ht/~akilan1999/p2p-rendering-computation/server/docker" "git.sr.ht/~akilan1999/p2p-rendering-computation/server/docker"
"strconv" "net"
"testing" "strconv"
"testing"
) )
// Test if the dummy plugin added is detected // Test if the dummy plugin added is detected
func TestDetectPlugins(t *testing.T) { func TestDetectPlugins(t *testing.T) {
_, err := DetectPlugins() _, err := DetectPlugins()
if err != nil { if err != nil {
t.Fail() t.Fail()
} }
} }
// Test ensures that the ansible are executed inside local containers // Test ensures that the ansible are executed inside local containers
func TestRunPlugin(t *testing.T) { func TestRunPlugin(t *testing.T) {
var testips []*ExecuteIP var testips []*ExecuteIP
var testip1,testip2 ExecuteIP var testip1, testip2 ExecuteIP
// Create docker container and get SSH port // Create docker container and get SSH port
container1 ,err := docker.BuildRunContainer(0,"false","") container1, err := docker.BuildRunContainer(0, "false", "")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
//Test IP 1 configuration //Test IP 1 configuration
testip1.IPAddress = "0.0.0.0" testip1.IPAddress = "0.0.0.0"
testip1.SSHPortNo = strconv.Itoa(container1.Ports.PortSet[0].ExternalPort) testip1.SSHPortNo = strconv.Itoa(container1.Ports.PortSet[0].ExternalPort)
// Create docker container and get SSH port // Create docker container and get SSH port
container2 ,err := docker.BuildRunContainer(0,"false","") container2, err := docker.BuildRunContainer(0, "false", "")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
//Test IP 2 configuration //Test IP 2 configuration
testip2.IPAddress = "0.0.0.0" testip2.IPAddress = "0.0.0.0"
testip2.SSHPortNo = strconv.Itoa(container2.Ports.PortSet[0].ExternalPort) testip2.SSHPortNo = strconv.Itoa(container2.Ports.PortSet[0].ExternalPort)
testips = append(testips, &testip1) testips = append(testips, &testip1)
testips = append(testips, &testip2) testips = append(testips, &testip2)
_,err = RunPlugin("TestAnsible",testips) _, err = RunPlugin("TestAnsible", testips)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Removing container1 after Ansible is executed // Removing container1 after Ansible is executed
err = docker.StopAndRemoveContainer(container1.ID) err = docker.StopAndRemoveContainer(container1.ID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
err = docker.StopAndRemoveContainer(container2.ID) err = docker.StopAndRemoveContainer(container2.ID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
} }
// Test to ensure that the ansible host file is modified to // Test to ensure that the ansible host file is modified to
// the appropriate IP // the appropriate IP
func TestExecuteIP_ModifyHost(t *testing.T) { func TestExecuteIP_ModifyHost(t *testing.T) {
var plugin Plugin var plugin Plugin
var testip ExecuteIP var testip ExecuteIP
// Get plugin path from config file // Get plugin path from config file
Config, err := config.ConfigInit() Config, err := config.ConfigInit()
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
//Set plugin name //Set plugin name
plugin.FolderName = "TestAnsible" plugin.FolderName = "TestAnsible"
plugin.path = Config.PluginPath plugin.path = Config.PluginPath
//Test IP 1 configuration //Test IP 1 configuration
testip.IPAddress = "0.0.0.0" testip.IPAddress = "0.0.0.0"
testip.SSHPortNo = "41289" testip.SSHPortNo = "41289"
err = testip.ModifyHost(&plugin) err = testip.ModifyHost(&plugin)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
} }
// Test to ensure the cli function runs as intended and executes // Test to ensure the cli function runs as intended and executes
// the test ansible script // the test ansible script
func TestRunPluginContainer(t *testing.T) { func TestRunPluginContainer(t *testing.T) {
// Create docker container and get SSH port // Create docker container and get SSH port
container1 ,err := docker.BuildRunContainer(0,"false","") container1, err := docker.BuildRunContainer(0, "false", "")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Ensuring created container is the added to the tracked list // Ensuring created container is the added to the tracked list
err = client.AddTrackContainer(container1, "0.0.0.0") err = client.AddTrackContainer(container1, "0.0.0.0")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Running test Ansible script // Running test Ansible script
err = RunPluginContainer("TestAnsible", container1.ID) err = RunPluginContainer("TestAnsible", container1.ID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Removes container information from the tracker IP addresses // Removes container information from the tracker IP addresses
err = client.RemoveTrackedContainer(container1.ID) err = client.RemoveTrackedContainer(container1.ID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Removing container1 after Ansible is executed // Removing container1 after Ansible is executed
err = docker.StopAndRemoveContainer(container1.ID) err = docker.StopAndRemoveContainer(container1.ID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
} }
// Testing the function can plugin can run with // Testing the function can plugin can run with
// group ID and container ID // group ID and container ID
func TestCheckRunPlugin(t *testing.T) { func TestCheckRunPlugin(t *testing.T) {
// Create docker container and get SSH port // Create docker container and get SSH port
container1 ,err := docker.BuildRunContainer(0,"false","") container1, err := docker.BuildRunContainer(0, "false", "")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Create docker container and get SSH port // Create docker container and get SSH port
container2 ,err := docker.BuildRunContainer(0,"false","") container2, err := docker.BuildRunContainer(0, "false", "")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Ensuring created container1 is the added to the tracked list // Ensuring created container1 is the added to the tracked list
err = client.AddTrackContainer(container1, "0.0.0.0") err = client.AddTrackContainer(container1, "0.0.0.0")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Ensuring created container2 is the added to the tracked list // Ensuring created container2 is the added to the tracked list
err = client.AddTrackContainer(container2, "0.0.0.0") err = client.AddTrackContainer(container2, "0.0.0.0")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Create group to add created containers // Create group to add created containers
group, err := client.CreateGroup() group, err := client.CreateGroup()
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Add container 1 to the group
_, err = client.AddContainerToGroup(container1.ID, group.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Add container 1 to the group // Add container 2 to the group
_, err = client.AddContainerToGroup(container1.ID, group.ID) _, err = client.AddContainerToGroup(container2.ID, group.ID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Add container 2 to the group // -------------------------- Main test cases -------------------------------
_, err = client.AddContainerToGroup(container2.ID, group.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// -------------------------- Main test cases ------------------------------- // Checking function against container ID
err = CheckRunPlugin("TestAnsible", container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Checking function against container ID // Checking function against group ID
err = CheckRunPlugin("TestAnsible", container1.ID) err = CheckRunPlugin("TestAnsible", group.ID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Checking function against group ID // ----------------------------------------------------------------------------
err = CheckRunPlugin("TestAnsible", group.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// ---------------------------------------------------------------------------- // Remove created group
err = client.RemoveGroup(group.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Remove created group // Removes container1 information from the tracker IP addresses
err = client.RemoveGroup(group.ID) err = client.RemoveTrackedContainer(container1.ID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Removes container1 information from the tracker IP addresses // Removing container1 after Ansible is executed
err = client.RemoveTrackedContainer(container1.ID) err = docker.StopAndRemoveContainer(container1.ID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Removing container1 after Ansible is executed // Removes container2 information from the tracker IP addresses
err = docker.StopAndRemoveContainer(container1.ID) err = client.RemoveTrackedContainer(container2.ID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Removes container2 information from the tracker IP addresses // Removing container2 after Ansible is executed
err = client.RemoveTrackedContainer(container2.ID) err = docker.StopAndRemoveContainer(container2.ID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
} }
// Removing container2 after Ansible is executed
err = docker.StopAndRemoveContainer(container2.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
} }
func TestDownloadPlugin(t *testing.T) { func TestDownloadPlugin(t *testing.T) {
err := DownloadPlugin("https://github.com/Akilan1999/laplace/") err := DownloadPlugin("https://github.com/Akilan1999/laplace/")
if err != nil { if err != nil {
} }
} }
// Simple test case implemented to the test if
// the port no can be extracted from the IP address.
func TestParseIP(t *testing.T) {
host, port, err := net.SplitHostPort("12.34.23.13:5432")
if err != nil {
fmt.Printf("Error: %v\n", err)
} else {
fmt.Printf("Host: %s\nPort: %s\n", host, port)
}
}