Merge pull request #73 from Akilan1999/automaticports
Setting automatic ports
This commit is contained in:
@@ -4,6 +4,8 @@
|
|||||||
2. [Site.yml](#site-File-Template)
|
2. [Site.yml](#site-File-Template)
|
||||||
3. [Host](#hosts-file)
|
3. [Host](#hosts-file)
|
||||||
4. [Description](#description-file)
|
4. [Description](#description-file)
|
||||||
|
5. [Automatic port allocations](#automatic-port-allocations)
|
||||||
|
6. [Sample plugins implemented](#sample-plugins-implemented)
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
@@ -84,4 +86,50 @@ Ex: When the flag ```--ViewPlugins``` or ```--vp``` is called
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Automatic port allocations
|
||||||
|
P2PRC would be in-charge to set to the ports to various TCP ports
|
||||||
|
opened. Due to this implementation the plugin being executed is
|
||||||
|
copied to the tmp directory with a unique UUID.
|
||||||
|
```
|
||||||
|
Command: ls /tmp
|
||||||
|
output: Semantic <UUID>_<Plugin Name>
|
||||||
|
2e6d76c4-0ed1-4b55-9385-79a58d4f0492_p2prc-vscode-browser
|
||||||
|
7b631e08-62ee-4c1c-a2a4-c05857b9aa7d_p2prc-vscode-browser
|
||||||
|
```
|
||||||
|
Once the copy of the plugin is added to the /tmp directory
|
||||||
|
the site.yml file inside the appropriate yaml is modified
|
||||||
|
with the appropriate ports assigned to the container.
|
||||||
|
|
||||||
|
### Ex:
|
||||||
|
1. Create container called c1 with an automatic generated TCP port
|
||||||
|
3313 (external) - 3313 (internal)
|
||||||
|
2. Assumption of plugin p1 exists. p1 has one server which needs to
|
||||||
|
be mapped to a free open TCP port in container c1. Below shows
|
||||||
|
an implementation of a sample site.yml file.
|
||||||
|
```
|
||||||
|
---
|
||||||
|
- hosts: all
|
||||||
|
tasks:
|
||||||
|
- name: start vscode code server
|
||||||
|
shell: sh server.sh 0.0.0.0:{{index . 0}}
|
||||||
|
```
|
||||||
|
Notice there is the following {{index . 0}}. {{index . 0}} does not belong to
|
||||||
|
Ansible but rather is a way to mention where to add the external free port
|
||||||
|
of the container. We use the golang [template library](https://pkg.go.dev/text/template)
|
||||||
|
to parse and populate the site.yml with the appropriate open ports. An array of ints
|
||||||
|
which consists of open free ports are sent to the site.yml. 0 in {{index . 0}} refers
|
||||||
|
to the index in the int array passed on.
|
||||||
|
|
||||||
|
After the port is automatically it's ready to run !
|
||||||
|
```
|
||||||
|
---
|
||||||
|
- hosts: all
|
||||||
|
tasks:
|
||||||
|
- name: start vscode code server
|
||||||
|
shell: sh server.sh 0.0.0.0:3313
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sample plugins implemented:
|
||||||
|
- [VSCode Plugin](https://github.com/Akilan1999/p2prc-vscode-browser)
|
||||||
|
|||||||
107
plugin/plugin.go
107
plugin/plugin.go
@@ -6,14 +6,18 @@ 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"
|
||||||
|
"github.com/google/uuid"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"strconv"
|
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Plugins Array of all plugins detected
|
// Plugins Array of all plugins detected
|
||||||
@@ -25,11 +29,13 @@ type Plugins struct {
|
|||||||
type Plugin struct {
|
type Plugin struct {
|
||||||
FolderName string
|
FolderName string
|
||||||
PluginDescription string
|
PluginDescription string
|
||||||
|
path string
|
||||||
Execute []*ExecuteIP
|
Execute []*ExecuteIP
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteIP IP Address to execute Ansible instruction
|
// ExecuteIP IP Address to execute Ansible instruction
|
||||||
type ExecuteIP struct {
|
type ExecuteIP struct {
|
||||||
|
ContainerID string
|
||||||
IPAddress string
|
IPAddress string
|
||||||
SSHPortNo string
|
SSHPortNo string
|
||||||
Success bool
|
Success bool
|
||||||
@@ -106,6 +112,12 @@ func RunPlugin(pluginName string ,IPAddresses []*ExecuteIP) (*Plugin,error) {
|
|||||||
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
|
||||||
|
config, err := config.ConfigInit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
plugindetected.path = config.PluginPath
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,6 +125,14 @@ func RunPlugin(pluginName string ,IPAddresses []*ExecuteIP) (*Plugin,error) {
|
|||||||
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
|
// Executing the plugin
|
||||||
err = plugindetected.ExecutePlugin()
|
err = plugindetected.ExecutePlugin()
|
||||||
@@ -125,21 +145,20 @@ func RunPlugin(pluginName string ,IPAddresses []*ExecuteIP) (*Plugin,error) {
|
|||||||
|
|
||||||
// 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 {
|
||||||
// Get Execute plugin path from config file
|
|
||||||
config, err:= config.ConfigInit()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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,config.PluginPath)
|
err := execute.ModifyHost(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// sets the ports to the plugin folder
|
||||||
err = execute.RunAnsible(p,config.PluginPath)
|
err = p.AutoSetPorts(execute.ContainerID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = execute.RunAnsible(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -150,13 +169,13 @@ func (p *Plugin) ExecutePlugin() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RunAnsible Executes based on credentials on the struct
|
// RunAnsible Executes based on credentials on the struct
|
||||||
func (e *ExecuteIP)RunAnsible(p *Plugin,path string) 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: path + "/" + p.FolderName + "/hosts",
|
Inventory: p.path + "/" + p.FolderName + "/hosts",
|
||||||
ExtraVars: map[string]interface{}{"host_key_checking":"false"},
|
ExtraVars: map[string]interface{}{"host_key_checking":"false"},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +184,7 @@ func (e *ExecuteIP)RunAnsible(p *Plugin,path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
playbook := &playbook.AnsiblePlaybookCmd{
|
playbook := &playbook.AnsiblePlaybookCmd{
|
||||||
Playbooks: []string{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,
|
||||||
@@ -185,8 +204,8 @@ func (e *ExecuteIP)RunAnsible(p *Plugin,path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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, path string) error {
|
func (e *ExecuteIP)ModifyHost(p *Plugin) error {
|
||||||
host,err := ReadHost(path + "/" + p.FolderName + "/hosts")
|
host,err := ReadHost(p.path + "/" + p.FolderName + "/hosts")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -209,7 +228,7 @@ func (e *ExecuteIP)ModifyHost(p *Plugin, path string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = ioutil.WriteFile(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
|
||||||
}
|
}
|
||||||
@@ -232,7 +251,7 @@ func ReadHost(filename string) (*Host, error) {
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunPluginContainer Runs ansible plugin based on plugin name and contianer 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
|
||||||
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
|
||||||
@@ -257,6 +276,8 @@ func RunPluginContainer(PluginName string, ContainerID string) error {
|
|||||||
}
|
}
|
||||||
// IP address of the container
|
// IP address of the container
|
||||||
ExecuteIP.IPAddress = ContainerInformation.IpAddress
|
ExecuteIP.IPAddress = ContainerInformation.IpAddress
|
||||||
|
// 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
|
||||||
@@ -301,3 +322,59 @@ func CheckRunPlugin(PluginName string, ID string) error {
|
|||||||
|
|
||||||
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// setting all external ports available in an array
|
||||||
|
for _, port := range container.Container.Ports.PortSet {
|
||||||
|
if port.InternalPort == port.ExternalPort {
|
||||||
|
ports = append(ports, port.ExternalPort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// parses the site.yml file in the tmp directory
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -80,12 +80,13 @@ func TestExecuteIP_ModifyHost(t *testing.T) {
|
|||||||
}
|
}
|
||||||
//Set plugin name
|
//Set plugin name
|
||||||
plugin.FolderName = "TestAnsible"
|
plugin.FolderName = "TestAnsible"
|
||||||
|
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,Config.PluginPath)
|
err = testip.ModifyHost(&plugin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
t.Fail()
|
t.Fail()
|
||||||
|
|||||||
Reference in New Issue
Block a user