diff --git a/config/config.go b/config/config.go index 9482154..897ed12 100644 --- a/config/config.go +++ b/config/config.go @@ -29,6 +29,7 @@ type Config struct { GroupTrackContainersPath string FRPServerPort string BehindNAT string + AnsibleConfig string //NetworkInterface string //NetworkInterfaceIPV6Index int } @@ -127,6 +128,7 @@ func SetDefaults() error { defaults["ServerPort"] = "8088" defaults["FRPServerPort"] = "0" defaults["BehindNAT"] = "True" + defaults["AnsibleConfig"] = defaultPath + "p2p/ansible/ansible.cfg" // Random name generator hostname, err := os.Hostname() if err != nil { diff --git a/plugin/plugin.go b/plugin/plugin.go index cdef950..e402fd9 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -1,452 +1,464 @@ package plugin import ( - "context" - "encoding/json" - "errors" - "fmt" - "git.sr.ht/~akilan1999/p2p-rendering-computation/client" - "git.sr.ht/~akilan1999/p2p-rendering-computation/config" - "github.com/google/uuid" - "gopkg.in/yaml.v2" - "io/ioutil" - "os" - "strconv" - "text/template" + "context" + "encoding/json" + "errors" + "fmt" + "git.sr.ht/~akilan1999/p2p-rendering-computation/client" + "git.sr.ht/~akilan1999/p2p-rendering-computation/config" + "github.com/google/uuid" + "gopkg.in/yaml.v2" + "io/ioutil" + "net" + "os" + "strconv" + "text/template" - "github.com/apenella/go-ansible/pkg/execute" - "github.com/apenella/go-ansible/pkg/options" - "github.com/apenella/go-ansible/pkg/playbook" - "github.com/apenella/go-ansible/pkg/stdoutcallback/results" - "github.com/otiai10/copy" + "github.com/apenella/go-ansible/pkg/execute" + "github.com/apenella/go-ansible/pkg/options" + "github.com/apenella/go-ansible/pkg/playbook" + "github.com/apenella/go-ansible/pkg/stdoutcallback/results" + "github.com/otiai10/copy" ) // Plugins Array of all plugins detected type Plugins struct { - PluginsDetected []*Plugin + PluginsDetected []*Plugin } // Plugin Information about the plugins available type Plugin struct { - FolderName string - PluginDescription string - path string - Execute []*ExecuteIP - NumOfPorts int + FolderName string + PluginDescription string + path string + Execute []*ExecuteIP + NumOfPorts int } // ExecuteIP IP Address to execute Ansible instruction type ExecuteIP struct { - ContainerID string - IPAddress string - SSHPortNo string - Success bool + ContainerID string + IPAddress string + SSHPortNo string + Success bool } // Host Struct for ansible host // Generated from https://zhwt.github.io/yaml-to-go/ type Host struct { - All struct { - Vars struct { - AnsiblePythonInterpreter string `yaml:"ansible_python_interpreter"` - } `yaml:"vars"` - } `yaml:"all"` - Main struct { - Hosts struct { - Host1 struct { - AnsibleHost string `yaml:"ansible_host"` - AnsiblePort int `yaml:"ansible_port"` - AnsibleUser string `yaml:"ansible_user"` - AnsibleSSHPass string `yaml:"ansible_ssh_pass"` - AnsibleSudoPass string `yaml:"ansible_sudo_pass"` - } `yaml:"host1"` - } `yaml:"hosts"` - } `yaml:"main"` + All struct { + Vars struct { + AnsiblePythonInterpreter string `yaml:"ansible_python_interpreter"` + } `yaml:"vars"` + } `yaml:"all"` + Main struct { + Hosts struct { + Host1 struct { + AnsibleHost string `yaml:"ansible_host"` + AnsiblePort int `yaml:"ansible_port"` + AnsibleUser string `yaml:"ansible_user"` + AnsibleSSHPass string `yaml:"ansible_ssh_pass"` + AnsibleSudoPass string `yaml:"ansible_sudo_pass"` + } `yaml:"host1"` + } `yaml:"hosts"` + } `yaml:"main"` } // DetectPlugins Detects all the plugins available -func DetectPlugins()(*Plugins,error){ - config, err:= config.ConfigInit() - if err != nil { - return nil,err - } - folders, err := ioutil.ReadDir(config.PluginPath) - if err != nil { - return nil, err - } +func DetectPlugins() (*Plugins, error) { + config, err := config.ConfigInit() + if err != nil { + return nil, err + } + folders, err := ioutil.ReadDir(config.PluginPath) + if err != nil { + return nil, err + } - var plugins *Plugins = new(Plugins) + var plugins *Plugins = new(Plugins) - for _, f := range folders { - if f.IsDir() { - //Declare variable plugin of type Plugin - var plugin Plugin + for _, f := range folders { + if f.IsDir() { + //Declare variable plugin of type Plugin + var plugin Plugin - // Setting name of folder to plugin - plugin.FolderName = f.Name() - // Getting Description from file description.txt - Description, err := ioutil.ReadFile(config.PluginPath + "/" + plugin.FolderName + "/description.txt") - // if we os.Open returns an error then handle it - if err != nil { - return nil, err - } + // Setting name of folder to plugin + plugin.FolderName = f.Name() + // Getting Description from file description.txt + Description, err := ioutil.ReadFile(config.PluginPath + "/" + plugin.FolderName + "/description.txt") + // if we os.Open returns an error then handle it + if err != nil { + return nil, err + } - // Get Description from description.txt - plugin.PluginDescription = string(Description) - // Set plugin path - plugin.path = config.PluginPath + "/" + plugin.FolderName + // Get Description from description.txt + plugin.PluginDescription = string(Description) + // Set plugin path + plugin.path = config.PluginPath + "/" + plugin.FolderName - plugins.PluginsDetected = append(plugins.PluginsDetected, &plugin) - // Get the number of ports the plugin needs - err = plugin.NumPorts() - if err != nil { - return nil, err - } - } - } + plugins.PluginsDetected = append(plugins.PluginsDetected, &plugin) + // Get the number of ports the plugin needs + err = plugin.NumPorts() + if err != nil { + return nil, err + } + } + } - return plugins,nil + return plugins, nil } // SearchPlugin Detects plugin information based on the // name provided on the parameter -func SearchPlugin(pluginname string) (*Plugin,error) { - plugins, err := DetectPlugins() - if err != nil { - return nil, err - } +func SearchPlugin(pluginname string) (*Plugin, error) { + plugins, err := DetectPlugins() + if err != nil { + return nil, err + } - // loop ot find the plugin name that matches - for _, plugin := range plugins.PluginsDetected { - if pluginname == plugin.FolderName { - return plugin, nil - } - } + // loop ot find the plugin name that matches + for _, plugin := range plugins.PluginsDetected { + if pluginname == plugin.FolderName { + 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 -func RunPlugin(pluginName string ,IPAddresses []*ExecuteIP) (*Plugin,error) { - plugins, err := DetectPlugins() - if err != nil { - return nil,err - } +func RunPlugin(pluginName string, IPAddresses []*ExecuteIP) (*Plugin, error) { + plugins, err := DetectPlugins() + if err != nil { + return nil, err + } - // Variable to store struct information about the plugin - var plugindetected *Plugin - for _,plugin := range plugins.PluginsDetected { - if plugin.FolderName == pluginName { - plugindetected = plugin - plugindetected.Execute = IPAddresses - // Get Execute plugin path from config file - config, err := config.ConfigInit() - if err != nil { - return nil, err - } - plugindetected.path = config.PluginPath - break - } - } + // Variable to store struct information about the plugin + var plugindetected *Plugin + for _, plugin := range plugins.PluginsDetected { + if plugin.FolderName == pluginName { + plugindetected = plugin + plugindetected.Execute = IPAddresses + // Get Execute plugin path from config file + config, err := config.ConfigInit() + if err != nil { + return nil, err + } + plugindetected.path = config.PluginPath + break + } + } - if plugindetected == nil { - 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 - } + if plugindetected == nil { + return nil, errors.New("Plugin not detected") + } - // Executing the plugin - err = plugindetected.ExecutePlugin() - if err != nil { - return nil,err - } + // 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 + } - 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 func (p *Plugin) ExecutePlugin() error { - // Run ip address to execute ansible inside - for _,execute := range p.Execute { - // Modify ansible hosts before executing - err := execute.ModifyHost(p) - if err != nil { - return err - } - // sets the ports to the plugin folder - err = p.AutoSetPorts(execute.ContainerID) - if err != nil { - return err - } - err = execute.RunAnsible(p) - if err != nil { - return err - } - // If ran successfully then change success flag to true - execute.Success = true - } - return nil + // Run ip address to execute ansible inside + for _, execute := range p.Execute { + // Modify ansible hosts before executing + err := execute.ModifyHost(p) + if err != nil { + return err + } + // sets the ports to the plugin folder + err = p.AutoSetPorts(execute.ContainerID) + if err != nil { + return err + } + err = execute.RunAnsible(p) + if err != nil { + return err + } + // If ran successfully then change success flag to true + execute.Success = true + } + return nil } // RunAnsible Executes based on credentials on the struct -func (e *ExecuteIP)RunAnsible(p *Plugin) error { - ansiblePlaybookConnectionOptions := &options.AnsibleConnectionOptions{ - User: "master", - } +func (e *ExecuteIP) RunAnsible(p *Plugin) error { + ansiblePlaybookConnectionOptions := &options.AnsibleConnectionOptions{ + User: "master", + } - ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ - Inventory: p.path + "/" + p.FolderName + "/hosts", - ExtraVars: map[string]interface{}{"host_key_checking":"false"}, - } + ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ + Inventory: p.path + "/" + p.FolderName + "/hosts", + ExtraVars: map[string]interface{}{"ansible_ssh_common_args": "-o StrictHostKeyChecking=no"}, + } - ansiblePlaybookPrivilegeEscalationOptions := &options.AnsiblePrivilegeEscalationOptions{ - Become: true, - } + ansiblePlaybookPrivilegeEscalationOptions := &options.AnsiblePrivilegeEscalationOptions{ + Become: true, + } - playbook := &playbook.AnsiblePlaybookCmd{ - Playbooks: []string{p.path + "/" + p.FolderName + "/site.yml"}, - ConnectionOptions: ansiblePlaybookConnectionOptions, - PrivilegeEscalationOptions: ansiblePlaybookPrivilegeEscalationOptions, - Options: ansiblePlaybookOptions, - Exec: execute.NewDefaultExecute( - execute.WithTransformers( - results.Prepend("success"), - ), - ), - } + playbook := &playbook.AnsiblePlaybookCmd{ + Playbooks: []string{p.path + "/" + p.FolderName + "/site.yml"}, + ConnectionOptions: ansiblePlaybookConnectionOptions, + PrivilegeEscalationOptions: ansiblePlaybookPrivilegeEscalationOptions, + Options: ansiblePlaybookOptions, + Exec: execute.NewDefaultExecute( + execute.WithTransformers( + results.Prepend("success"), + ), + ), + } - err := playbook.Run(context.TODO()) - if err != nil { - return err - } + err := playbook.Run(context.TODO()) + if err != nil { + return err + } - return nil + return nil } // ModifyHost adds IP address , port no to the config file -func (e *ExecuteIP)ModifyHost(p *Plugin) error { - host,err := ReadHost(p.path + "/" + p.FolderName + "/hosts") +func (e *ExecuteIP) ModifyHost(p *Plugin) error { + host, err := ReadHost(p.path + "/" + p.FolderName + "/hosts") if err != nil { - return err - } + return err + } // Setting ansible host - host.Main.Hosts.Host1.AnsibleHost = e.IPAddress - // Setting SSH port no - host.Main.Hosts.Host1.AnsiblePort, err = strconv.Atoi(e.SSHPortNo) - if err != nil { - return err - } - // Setting SSH user name - host.Main.Hosts.Host1.AnsibleUser = "master" - // Setting SSH password - host.Main.Hosts.Host1.AnsibleSSHPass = "password" - // Setting SSH sudo password - host.Main.Hosts.Host1.AnsibleSudoPass = "password" + host.Main.Hosts.Host1.AnsibleHost = e.IPAddress + // Setting SSH port no + host.Main.Hosts.Host1.AnsiblePort, err = strconv.Atoi(e.SSHPortNo) + if err != nil { + return err + } + // Setting SSH user name + host.Main.Hosts.Host1.AnsibleUser = "master" + // Setting SSH password + host.Main.Hosts.Host1.AnsibleSSHPass = "password" + // Setting SSH sudo password + host.Main.Hosts.Host1.AnsibleSudoPass = "password" - // write modified information to the hosts yaml file - data,err := yaml.Marshal(host) - if err != nil { - return err - } - err = ioutil.WriteFile(p.path + "/" + p.FolderName + "/hosts",data,0777) - if err != nil { - return err - } - return nil + // write modified information to the hosts yaml file + data, err := yaml.Marshal(host) + if err != nil { + return err + } + err = ioutil.WriteFile(p.path+"/"+p.FolderName+"/hosts", data, 0777) + if err != nil { + return err + } + return nil } // ReadHost Reads host file and adds func ReadHost(filename string) (*Host, error) { - buf, err := ioutil.ReadFile(filename) - if err != nil { - return nil, err - } + buf, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } - c := &Host{} - err = yaml.Unmarshal(buf, c) - if err != nil { - return nil, fmt.Errorf("in file %q: %v", filename, err) - } + c := &Host{} + err = yaml.Unmarshal(buf, c) + if err != nil { + 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 // is derived from the tracked containers file // We pass in the group ID as a parameter because when we modify the ports taken func RunPluginContainer(PluginName string, ContainerID string) error { - // Gets container information based on container ID - ContainerInformation, err := client.GetContainerInformation(ContainerID) - if err != nil { - return err - } + // Gets container information based on container ID + ContainerInformation, err := client.GetContainerInformation(ContainerID) + if err != nil { + return err + } - // Setting Up IP's for which the plugins will be executed - var ExecuteIPs []*ExecuteIP - var ExecuteIP ExecuteIP - // Getting port no of SSH port - for _,port := range ContainerInformation.Container.Ports.PortSet { - if port.PortName == "SSH" { - ExecuteIP.SSHPortNo = fmt.Sprint(port.ExternalPort) - break - } - } - // Handle error if SSH port is not provided - if ExecuteIP.SSHPortNo == "" { - return errors.New("SSH port not found") - } - // IP address of the container - ExecuteIP.IPAddress = ContainerInformation.IpAddress - // Set container ID to ExecutorIP - ExecuteIP.ContainerID = ContainerInformation.Id + // Setting Up IP's for which the plugins will be executed + var ExecuteIPs []*ExecuteIP + var ExecuteIP ExecuteIP + // Getting port no of SSH port + for _, port := range ContainerInformation.Container.Ports.PortSet { + if port.PortName == "SSH" { + ExecuteIP.SSHPortNo = fmt.Sprint(port.ExternalPort) + break + } + } + // Handle error if SSH port is not provided + if ExecuteIP.SSHPortNo == "" { + return errors.New("SSH port not found") + } + // Split the port no from ip address since current the IP address + // field is populated as + // : + + 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 - ExecuteIPs = append(ExecuteIPs, &ExecuteIP) - // Run plugin to execute plugin - _, err = RunPlugin(PluginName,ExecuteIPs) - if err != nil { - return err - } + ExecuteIPs = append(ExecuteIPs, &ExecuteIP) + // Run plugin to execute plugin + _, err = RunPlugin(PluginName, ExecuteIPs) + if err != nil { + return err + } - return nil + return nil } // CheckRunPlugin Checks if the ID belongs to the group or container // calls the plugin function the appropriate amount of times func CheckRunPlugin(PluginName string, ID string) error { - // Check if the ID belongs to the group or container ID - id, err := client.CheckID(ID) - if err != nil { - return err - } - // When the ID belongs to a group - if id == "group" { - // gets the group information - group, err := client.GetGroup(ID) - if err != nil { - return err - } - // Iterate through each container information in the group - // and run the plugin in each of them - for _, container := range group.TrackContainerList { - // runs plugin for each container - err := RunPluginContainer(PluginName, container.Id) - if err != nil { - return err - } - } - } else { // This means the following ID is a container ID - err := RunPluginContainer(PluginName, ID) - if err != nil { - return err - } - } + // Check if the ID belongs to the group or container ID + id, err := client.CheckID(ID) + if err != nil { + return err + } + // When the ID belongs to a group + if id == "group" { + // gets the group information + group, err := client.GetGroup(ID) + if err != nil { + return err + } + // Iterate through each container information in the group + // and run the plugin in each of them + for _, container := range group.TrackContainerList { + // runs plugin for each container + err := RunPluginContainer(PluginName, container.Id) + if err != nil { + return err + } + } + } else { // This means the following ID is a container ID + err := RunPluginContainer(PluginName, ID) + if err != nil { + return err + } + } - return nil + return nil } // CopyToTmpPlugin This function would ensure that we create a copy of the // plugin in the tmp directory, and it would be executed // from there. This due to the reason of automating port allocation // when running plugins -func (p *Plugin)CopyToTmpPlugin() error { - // generate rand to UUID this is debug the ansible file if needed - id := uuid.New() - // copies the plugin to the tmp directory - err := copy.Copy(p.path+"/"+p.FolderName, "/tmp/"+ id.String() + "_" + p.FolderName) - if err != nil { - return err - } +func (p *Plugin) CopyToTmpPlugin() error { + // generate rand to UUID this is debug the ansible file if needed + id := uuid.New() + // copies the plugin to the tmp directory + err := copy.Copy(p.path+"/"+p.FolderName, "/tmp/"+id.String()+"_"+p.FolderName) + if err != nil { + return err + } - // Set the plugin execution to the tmp location - p.path = "/tmp" - p.FolderName = id.String() + "_" + p.FolderName + // Set the plugin execution to the tmp location + p.path = "/tmp" + p.FolderName = id.String() + "_" + p.FolderName return nil } // AutoSetPorts Automatically maps free ports to site.yml file -func (p *Plugin)AutoSetPorts(containerID string) error { - container , err := client.GetContainerInformation(containerID) - if err != nil { - return err - } - // variable that would have a list of ports - // to be allocated to the plugin system - var ports []int - // Counted that increments when a port is taken - PortTaken := 0 - // setting all external ports available in an array - for i, port := range container.Container.Ports.PortSet { - if port.IsUsed == false { - // Ensuring we break outside the loop once the ports - // are set. - if PortTaken >= p.NumOfPorts { - break - } - // Setting the following port flag to true - container.Container.Ports.PortSet[i].IsUsed = true - // Incrementing the variable PortTaken - PortTaken++ - ports = append(ports, port.ExternalPort) - } - } +func (p *Plugin) AutoSetPorts(containerID string) error { + container, err := client.GetContainerInformation(containerID) + if err != nil { + return err + } + // variable that would have a list of ports + // to be allocated to the plugin system + var ports []int + // Counted that increments when a port is taken + PortTaken := 0 + // setting all external ports available in an array + for i, port := range container.Container.Ports.PortSet { + if port.IsUsed == false { + // Ensuring we break outside the loop once the ports + // are set. + if PortTaken >= p.NumOfPorts { + break + } + // Setting the following port flag to true + container.Container.Ports.PortSet[i].IsUsed = true + // Incrementing the variable PortTaken + PortTaken++ + // 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 - t, err := template.ParseFiles(p.path + "/" + p.FolderName + "/site.yml") - if err != nil { - return err - } + t, err := template.ParseFiles(p.path + "/" + p.FolderName + "/site.yml") + if err != nil { + return err + } // opens the output file - f, err := os.Create(p.path + "/" + p.FolderName + "/site.yml") - if err != nil { - return err - } - // sends the ports to the site.yml file to populate them - err = t.Execute(f,ports) - if err != nil { - return err - } - // Once the following is done set port to taken - // n tracked container list - err = container.ModifyContainerInformation() - if err != nil { - return err - } - // Once the following is done set port to taken - // I(Groups) - err = container.ModifyContainerGroups() - if err != nil { - return err - } + f, err := os.Create(p.path + "/" + p.FolderName + "/site.yml") + if err != nil { + return err + } + // sends the ports to the site.yml file to populate them + err = t.Execute(f, ports) + if err != nil { + return err + } + // Once the following is done set port to taken + // n tracked container list + err = container.ModifyContainerInformation() + if err != nil { + return err + } + // Once the following is done set port to taken + // I(Groups) + err = container.ModifyContainerGroups() + if err != nil { + return err + } - return nil + return nil } // NumPorts Gets the Number the ports the // plugin requires -func (p *Plugin)NumPorts() error { - jsonFile, err := os.Open(p.path + "/ports.json") - // if we os.Open returns an error then handle it - if err != nil { - return err - } +func (p *Plugin) NumPorts() error { + jsonFile, err := os.Open(p.path + "/ports.json") + // if we os.Open returns an error then handle it + if err != nil { + return err + } - // defer the closing of our jsonFile so that we can parse it later on - defer jsonFile.Close() + // defer the closing of our jsonFile so that we can parse it later on + defer jsonFile.Close() - // read our opened xmlFile as a byte array. - byteValue, _ := ioutil.ReadAll(jsonFile) + // read our opened xmlFile as a byte array. + byteValue, _ := ioutil.ReadAll(jsonFile) - // we unmarshal our byteArray which contains our - // jsonFile's content into 'users' which we defined above - json.Unmarshal(byteValue, &p) + // we unmarshal our byteArray which contains our + // jsonFile's content into 'users' which we defined above + json.Unmarshal(byteValue, &p) - return nil + return nil } diff --git a/plugin/plugin_test.go b/plugin/plugin_test.go index aeb1e49..01c29ff 100644 --- a/plugin/plugin_test.go +++ b/plugin/plugin_test.go @@ -1,246 +1,257 @@ package plugin import ( - "fmt" - "git.sr.ht/~akilan1999/p2p-rendering-computation/client" - "git.sr.ht/~akilan1999/p2p-rendering-computation/config" - "git.sr.ht/~akilan1999/p2p-rendering-computation/server/docker" - "strconv" - "testing" + "fmt" + "git.sr.ht/~akilan1999/p2p-rendering-computation/client" + "git.sr.ht/~akilan1999/p2p-rendering-computation/config" + "git.sr.ht/~akilan1999/p2p-rendering-computation/server/docker" + "net" + "strconv" + "testing" ) // Test if the dummy plugin added is detected func TestDetectPlugins(t *testing.T) { - _, err := DetectPlugins() - if err != nil { - t.Fail() - } + _, err := DetectPlugins() + if err != nil { + t.Fail() + } } // Test ensures that the ansible are executed inside local containers func TestRunPlugin(t *testing.T) { - var testips []*ExecuteIP - var testip1,testip2 ExecuteIP + var testips []*ExecuteIP + var testip1, testip2 ExecuteIP - // Create docker container and get SSH port - container1 ,err := docker.BuildRunContainer(0,"false","") - if err != nil { - fmt.Println(err) - t.Fail() - } + // Create docker container and get SSH port + container1, err := docker.BuildRunContainer(0, "false", "") + if err != nil { + fmt.Println(err) + t.Fail() + } - //Test IP 1 configuration - testip1.IPAddress = "0.0.0.0" - testip1.SSHPortNo = strconv.Itoa(container1.Ports.PortSet[0].ExternalPort) + //Test IP 1 configuration + testip1.IPAddress = "0.0.0.0" + testip1.SSHPortNo = strconv.Itoa(container1.Ports.PortSet[0].ExternalPort) - // Create docker container and get SSH port - container2 ,err := docker.BuildRunContainer(0,"false","") - if err != nil { - fmt.Println(err) - t.Fail() - } - //Test IP 2 configuration - testip2.IPAddress = "0.0.0.0" - testip2.SSHPortNo = strconv.Itoa(container2.Ports.PortSet[0].ExternalPort) + // Create docker container and get SSH port + container2, err := docker.BuildRunContainer(0, "false", "") + if err != nil { + fmt.Println(err) + t.Fail() + } + //Test IP 2 configuration + testip2.IPAddress = "0.0.0.0" + testip2.SSHPortNo = strconv.Itoa(container2.Ports.PortSet[0].ExternalPort) - testips = append(testips, &testip1) - testips = append(testips, &testip2) + testips = append(testips, &testip1) + testips = append(testips, &testip2) - _,err = RunPlugin("TestAnsible",testips) - if err != nil { - fmt.Println(err) - t.Fail() - } + _, err = RunPlugin("TestAnsible", testips) + if err != nil { + fmt.Println(err) + t.Fail() + } - // Removing container1 after Ansible is executed - err = docker.StopAndRemoveContainer(container1.ID) - if err != nil { - fmt.Println(err) - t.Fail() - } + // Removing container1 after Ansible is executed + err = docker.StopAndRemoveContainer(container1.ID) + if err != nil { + fmt.Println(err) + t.Fail() + } - err = docker.StopAndRemoveContainer(container2.ID) - if err != nil { - fmt.Println(err) - t.Fail() - } + err = docker.StopAndRemoveContainer(container2.ID) + if err != nil { + fmt.Println(err) + t.Fail() + } } // Test to ensure that the ansible host file is modified to // the appropriate IP func TestExecuteIP_ModifyHost(t *testing.T) { - var plugin Plugin - var testip ExecuteIP + var plugin Plugin + var testip ExecuteIP - // Get plugin path from config file - Config, err := config.ConfigInit() - if err != nil { - fmt.Println(err) - t.Fail() - } - //Set plugin name - plugin.FolderName = "TestAnsible" - plugin.path = Config.PluginPath + // Get plugin path from config file + Config, err := config.ConfigInit() + if err != nil { + fmt.Println(err) + t.Fail() + } + //Set plugin name + plugin.FolderName = "TestAnsible" + plugin.path = Config.PluginPath - //Test IP 1 configuration - testip.IPAddress = "0.0.0.0" - testip.SSHPortNo = "41289" + //Test IP 1 configuration + testip.IPAddress = "0.0.0.0" + testip.SSHPortNo = "41289" - err = testip.ModifyHost(&plugin) - if err != nil { - fmt.Println(err) - t.Fail() - } + err = testip.ModifyHost(&plugin) + if err != nil { + fmt.Println(err) + t.Fail() + } } // Test to ensure the cli function runs as intended and executes // the test ansible script func TestRunPluginContainer(t *testing.T) { - // Create docker container and get SSH port - container1 ,err := docker.BuildRunContainer(0,"false","") - if err != nil { - fmt.Println(err) - t.Fail() - } + // Create docker container and get SSH port + container1, err := docker.BuildRunContainer(0, "false", "") + if err != nil { + fmt.Println(err) + t.Fail() + } - // Ensuring created container is the added to the tracked list - err = client.AddTrackContainer(container1, "0.0.0.0") - if err != nil { - fmt.Println(err) - t.Fail() - } + // Ensuring created container is the added to the tracked list + err = client.AddTrackContainer(container1, "0.0.0.0") + if err != nil { + fmt.Println(err) + t.Fail() + } - // Running test Ansible script - err = RunPluginContainer("TestAnsible", container1.ID) - if err != nil { - fmt.Println(err) - t.Fail() - } + // Running test Ansible script + err = RunPluginContainer("TestAnsible", container1.ID) + if err != nil { + fmt.Println(err) + t.Fail() + } - // Removes container information from the tracker IP addresses - err = client.RemoveTrackedContainer(container1.ID) - if err != nil { - fmt.Println(err) - t.Fail() - } + // Removes container information from the tracker IP addresses + err = client.RemoveTrackedContainer(container1.ID) + if err != nil { + fmt.Println(err) + t.Fail() + } - // Removing container1 after Ansible is executed - err = docker.StopAndRemoveContainer(container1.ID) - if err != nil { - fmt.Println(err) - t.Fail() - } + // Removing container1 after Ansible is executed + err = docker.StopAndRemoveContainer(container1.ID) + if err != nil { + fmt.Println(err) + t.Fail() + } } // Testing the function can plugin can run with // group ID and container ID func TestCheckRunPlugin(t *testing.T) { - // Create docker container and get SSH port - container1 ,err := docker.BuildRunContainer(0,"false","") - if err != nil { - fmt.Println(err) - t.Fail() - } - // Create docker container and get SSH port - container2 ,err := docker.BuildRunContainer(0,"false","") - if err != nil { - fmt.Println(err) - t.Fail() - } + // Create docker container and get SSH port + container1, err := docker.BuildRunContainer(0, "false", "") + if err != nil { + fmt.Println(err) + t.Fail() + } + // Create docker container and get SSH port + container2, err := docker.BuildRunContainer(0, "false", "") + if err != nil { + fmt.Println(err) + t.Fail() + } - // Ensuring created container1 is the added to the tracked list - err = client.AddTrackContainer(container1, "0.0.0.0") - if err != nil { - fmt.Println(err) - t.Fail() - } - // Ensuring created container2 is the added to the tracked list - err = client.AddTrackContainer(container2, "0.0.0.0") - if err != nil { - fmt.Println(err) - t.Fail() - } + // Ensuring created container1 is the added to the tracked list + err = client.AddTrackContainer(container1, "0.0.0.0") + if err != nil { + fmt.Println(err) + t.Fail() + } + // Ensuring created container2 is the added to the tracked list + err = client.AddTrackContainer(container2, "0.0.0.0") + if err != nil { + fmt.Println(err) + t.Fail() + } - // Create group to add created containers - group, err := client.CreateGroup() - if err != nil { - fmt.Println(err) - t.Fail() - } + // Create group to add created containers + group, err := client.CreateGroup() + if err != nil { + fmt.Println(err) + 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 - _, err = client.AddContainerToGroup(container1.ID, group.ID) - if err != nil { - fmt.Println(err) - t.Fail() - } + // Add container 2 to the group + _, err = client.AddContainerToGroup(container2.ID, group.ID) + if err != nil { + fmt.Println(err) + t.Fail() + } - // Add container 2 to the group - _, err = client.AddContainerToGroup(container2.ID, group.ID) - if err != nil { - fmt.Println(err) - t.Fail() - } + // -------------------------- Main test cases ------------------------------- - // -------------------------- 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 - err = CheckRunPlugin("TestAnsible", container1.ID) - if err != nil { - fmt.Println(err) - t.Fail() - } + // Checking function against group ID + err = CheckRunPlugin("TestAnsible", group.ID) + if err != nil { + fmt.Println(err) + 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 - err = client.RemoveGroup(group.ID) - if err != nil { - fmt.Println(err) - t.Fail() - } + // Removes container1 information from the tracker IP addresses + err = client.RemoveTrackedContainer(container1.ID) + if err != nil { + fmt.Println(err) + t.Fail() + } - // Removes container1 information from the tracker IP addresses - err = client.RemoveTrackedContainer(container1.ID) - if err != nil { - fmt.Println(err) - t.Fail() - } + // Removing container1 after Ansible is executed + err = docker.StopAndRemoveContainer(container1.ID) + if err != nil { + fmt.Println(err) + t.Fail() + } - // Removing container1 after Ansible is executed - err = docker.StopAndRemoveContainer(container1.ID) - if err != nil { - fmt.Println(err) - t.Fail() - } + // Removes container2 information from the tracker IP addresses + err = client.RemoveTrackedContainer(container2.ID) + if err != nil { + fmt.Println(err) + t.Fail() + } - // Removes container2 information from the tracker IP addresses - err = client.RemoveTrackedContainer(container2.ID) - if err != nil { - fmt.Println(err) - t.Fail() - } - - // Removing container2 after Ansible is executed - err = docker.StopAndRemoveContainer(container2.ID) - if err != nil { - fmt.Println(err) - 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) { - err := DownloadPlugin("https://github.com/Akilan1999/laplace/") - if err != nil { + err := DownloadPlugin("https://github.com/Akilan1999/laplace/") + if err != nil { - } -} \ No newline at end of file + } +} + +// 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) + } +}