Compare commits
119 Commits
v1.0.0-bet
...
v1.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
| b82d56b8d0 | |||
|
|
9d99875cb8 | ||
| f63696d9da | |||
| 0144e59d71 | |||
|
|
8be15ca19b | ||
|
|
c5efee3932 | ||
|
|
b325b848d1 | ||
|
|
57cf1f984b | ||
|
|
d7b7e6b84b | ||
| eb1644367e | |||
| ab2a0b28f9 | |||
| 9f304d26c1 | |||
| 56be275759 | |||
| a06e1be2bc | |||
| d45bc99be7 | |||
|
|
dec76d254f | ||
| 91b15e3bd7 | |||
| 9d8303d66c | |||
| 2a7d8e154d | |||
|
|
519801d2c0 | ||
| fc5e834552 | |||
|
|
be985942b9 | ||
| 1ca73faaed | |||
|
|
5da700a9d0 | ||
|
|
86a266b017 | ||
| e9cc304d02 | |||
| 6b43d94e8d | |||
|
|
64580fade0 | ||
|
|
ddf0879f90 | ||
|
|
e9ce832893 | ||
|
|
24b1a1f8b6 | ||
|
|
f781cc28fc | ||
|
|
c83ebbe149 | ||
| 9d69aed8ce | |||
| 65de9dda17 | |||
| c3a3a21132 | |||
|
|
f0bdb44e7c | ||
| ce5b7aa1af | |||
| e4b1aaf208 | |||
| 5823cf2028 | |||
| 5c2b36c086 | |||
| 8fd9ccfa2d | |||
| 85bf56ec01 | |||
| e5334cbd3c | |||
|
|
fd9d5e1419 | ||
|
|
111c5ef93c | ||
|
|
1a7035164b | ||
| 554b08d6be | |||
| 8b95d05986 | |||
| ab2bcb393b | |||
| 4ed2e10ac3 | |||
|
|
8a278239ba | ||
|
|
51e9e38122 | ||
|
|
a047c630d7 | ||
| 6b4b028b6f | |||
| dab82ae3cf | |||
| e3088a36e1 | |||
| 7a9a6b7ac5 | |||
| c7985ed318 | |||
| a920ff749b | |||
| 1fe5db06c0 | |||
| d288d1f2d6 | |||
| e2f8df9dcb | |||
| 707592195a | |||
| 10e5c72c90 | |||
|
|
fa61b70d41 | ||
|
|
b8aa24d49e | ||
|
|
7f3e0a466f | ||
|
|
7fd33ceb4c | ||
|
|
4c43ab77bb | ||
| 4e133ed789 | |||
| 5ff6702d9c | |||
|
|
af4b129bee | ||
|
|
b776b3e1e1 | ||
|
|
47dc49867b | ||
|
|
340177e992 | ||
|
|
e893674180 | ||
|
|
b8e2a0047f | ||
|
|
7f48b7fb3d | ||
| 116cd7e0bd | |||
|
|
3e6c3b8a18 | ||
| 1411a5c0da | |||
|
|
1063fa5fd7 | ||
| 2aea584f8b | |||
| 088c9c5ba4 | |||
|
|
3ca75a540b | ||
| 4e0fd09d73 | |||
|
|
c3647c2fe7 | ||
| a9f3d39bbb | |||
| fc87d95753 | |||
| c22f73ad28 | |||
| e98f4119da | |||
|
|
c42725743d | ||
|
|
1877420fc6 | ||
|
|
decb1c0e10 | ||
| a416578702 | |||
| 489ffd6d0c | |||
| 51110c235b | |||
| 726292a77d | |||
| 92cd9fe1ab | |||
|
|
739c7305a8 | ||
| 75a4bed9d1 | |||
| 0131ce5765 | |||
| 326ebe1697 | |||
| b6d757d5e3 | |||
| 022558f740 | |||
| 58b8af4b6e | |||
| ef031c5b68 | |||
| de14a5fb06 | |||
| 1a0184406d | |||
| 0069308a2a | |||
| 378c8bb75e | |||
|
|
a73469155f | ||
|
|
0a28f22c76 | ||
| a3ddad6aca | |||
|
|
08f58a00c5 | ||
| 0ecd8355b5 | |||
| 63f570bb4f | |||
| 02f72209dc |
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: akilan1999
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
62
.github/release-drafter.yml
vendored
Normal file
62
.github/release-drafter.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: Release Drafter
|
||||
|
||||
on:
|
||||
push:
|
||||
# branches to consider in the event; optional, defaults to all
|
||||
branches:
|
||||
- master
|
||||
# pull_request event is required only for autolabeler
|
||||
pull_request:
|
||||
# Only following types are handled by the action, but one can default to all as well
|
||||
types: [opened, reopened, synchronize]
|
||||
|
||||
jobs:
|
||||
update_release_draft:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# (Optional) GitHub Enterprise requires GHE_HOST variable set
|
||||
#- name: Set GHE_HOST
|
||||
# run: |
|
||||
# echo "GHE_HOST=${GITHUB_SERVER_URL##https:\/\/}" >> $GITHUB_ENV
|
||||
|
||||
# Drafts your next Release notes as Pull Requests are merged into "master"
|
||||
- uses: release-drafter/release-drafter@v5
|
||||
# (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml
|
||||
# with:
|
||||
# config-name: my-config.yml
|
||||
# disable-autolabeler: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
name-template: 'v$RESOLVED_VERSION'
|
||||
tag-template: 'v$RESOLVED_VERSION'
|
||||
categories:
|
||||
- title: '🚀 Features'
|
||||
labels:
|
||||
- 'feature'
|
||||
- 'enhancement'
|
||||
- title: '🐛 Bug Fixes'
|
||||
labels:
|
||||
- 'fix'
|
||||
- 'bugfix'
|
||||
- 'bug'
|
||||
- title: '🧰 Maintenance'
|
||||
label: 'chore'
|
||||
|
||||
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
||||
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
|
||||
version-resolver:
|
||||
major:
|
||||
labels:
|
||||
- 'major'
|
||||
minor:
|
||||
labels:
|
||||
- 'minor'
|
||||
patch:
|
||||
labels:
|
||||
- 'patch'
|
||||
default: patch
|
||||
template: |
|
||||
## Changes
|
||||
|
||||
$CHANGES
|
||||
12
.gitignore
vendored
12
.gitignore
vendored
@@ -10,4 +10,14 @@ config.json
|
||||
.vscode/
|
||||
|
||||
#ignore generated iptables
|
||||
p2p/iptable/
|
||||
p2p/iptable/
|
||||
#ignore plugins added
|
||||
plugin/deploy/
|
||||
#ignore track container file
|
||||
client/trackcontainers/
|
||||
# Test generated files
|
||||
generate/p2prctest
|
||||
generate/Test
|
||||
#ignore windows exe files
|
||||
*.exe
|
||||
dist/
|
||||
|
||||
32
.goreleaser.yml
Normal file
32
.goreleaser.yml
Normal file
@@ -0,0 +1,32 @@
|
||||
# This is an example .goreleaser.yml file with some sensible defaults.
|
||||
# Make sure to check the documentation at https://goreleaser.com
|
||||
before:
|
||||
hooks:
|
||||
# You may remove this if you don't use go modules.
|
||||
- go mod tidy
|
||||
# you may remove this if you don't need go generate
|
||||
- go generate ./...
|
||||
builds:
|
||||
- env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
- windows
|
||||
- darwin
|
||||
archives:
|
||||
- replacements:
|
||||
darwin: Darwin
|
||||
linux: Linux
|
||||
windows: Windows
|
||||
386: i386
|
||||
amd64: x86_64
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
snapshot:
|
||||
name_template: "{{ incpatch .Version }}-next"
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
exclude:
|
||||
- '^docs:'
|
||||
- '^test:'
|
||||
9
CITATION.cff
Normal file
9
CITATION.cff
Normal file
@@ -0,0 +1,9 @@
|
||||
cff-version: 1.0.0
|
||||
message: "If you use this software, please cite it as below."
|
||||
authors:
|
||||
- family-names: Selvacoumar
|
||||
given-names: Akilan
|
||||
title: P2PRC
|
||||
license: "GPL-2.0"
|
||||
version: 1.0.0
|
||||
date-released: 2021-07-22
|
||||
@@ -1,10 +1,16 @@
|
||||
# Client Module Implementation
|
||||
|
||||
This section focuses in depth on how the client module works. To understand the architecture of
|
||||
the client module refer to section 4.2. The client module is incharge of communicating with
|
||||
## Topics
|
||||
1. [Updating the IP table](#updating-the-IP-table)
|
||||
2. [Reading server specifications](#reading-server-specifications)
|
||||
3. [Client creating and removing container](#Client-creating-and-removing-container)
|
||||
4. [Tracking Containers](#Tracking-Containers)
|
||||
5. [Grouping Containers](#Grouping-Containers)
|
||||
|
||||
This section focuses in depth on how the client module works. The client module is incharge of communicating with
|
||||
different servers based on the IP addresses provided to the user. The IP addresses are derived
|
||||
from peer to peer modules. Section 5.6 talks more in depth regarding the peer to peer module.
|
||||
The objective here is how the client module interacts with peer to peer module and server module.
|
||||
from peer to peer modules. The objective here is how the client module interacts with peer to peer module
|
||||
and server module.
|
||||
|
||||
### Updating the IP table
|
||||
The client module calls the peer to peer module to get the local IP table initially, Based on the
|
||||
@@ -31,4 +37,49 @@ the container ID, ports open , SSH username, SSH password, VNC username and VNC
|
||||
At the moment the username and password are hard coded from the server side for both SSH and
|
||||
VNC.
|
||||
To remove a container the client module only requires the server IP address and the container ID.
|
||||
The client prints the response from the server Rest api.
|
||||
The client prints the response from the server Rest api.
|
||||
|
||||
### Tracking Containers
|
||||
Clients create docker images in multiple machines. This means if the client (i.e user) has many
|
||||
containers created there needs to be a way to track them. To track containers there is a file
|
||||
called ```trackcontainers.json``` which tracks all the containers running. The snippet below
|
||||
show a sample structure of file ```trackcontainer.json```.
|
||||
|
||||
```
|
||||
{
|
||||
"TrackContainer": [
|
||||
{
|
||||
"ID": "<ID>",
|
||||
"Container": {<docker.DockerVM struct>},
|
||||
"IpAddress": "<IP Address>"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
The default path to the container tracker is ```client/trackcontainers/trackcontainers.json```.
|
||||
|
||||
### Grouping Containers
|
||||
When starting a set container possibility to be able to group them.
|
||||
The benefit this would be that when executing plugins the group ID would be enough to execute
|
||||
plugin in a set of containers. This provides the possibility to execute repetitive tasks in containers in
|
||||
a single cli command. To store groups there is a file called ```grouptrackcontainer.json``` which tracks all
|
||||
the groups currently present set by the client. The snippet below
|
||||
show a sample structure of file ```grouptrackcontainer.json```.
|
||||
|
||||
```
|
||||
{
|
||||
"Groups": [
|
||||
{
|
||||
"ID": "grp<Random UUID>",
|
||||
"TrackContainer": [{client.TrackContainers struct}]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
The default path to the container tracker is ```client/trackcontainers/grouptrackcontainer.json```.
|
||||
|
||||
### Note:
|
||||
The group id will be auto-generated and will have its own prefix in the start which will mostly be ```grp<UUID>```.
|
||||
When a container is removed using the command. ```p2prc --rm <IP Address> --id <Container id>```. It will be automatically deleted
|
||||
from the groups it exists in.
|
||||
|
||||
|
||||
116
Docs/GenerateImplementation.md
Normal file
116
Docs/GenerateImplementation.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# Generate Module
|
||||
P2PRC is a great layer of abstraction. This means that in many cases it is not an end product but rather
|
||||
a tool that customized as an end product. An example would be writing your own billing module to monetize
|
||||
the computation power available. The generate module copies the current with the appropriate git histories
|
||||
and keeps only the go files which would be useful to edit. To use the generate module the user will need
|
||||
to have a go compiler present in his computer. Due to the introduction of this module there will 2 releases:
|
||||
|
||||
- Regular Release (Consists of only the build binary and cli command cannot access the generate module)
|
||||
- Developer Release (Consists of important Go files and the cli can access the generate module)
|
||||
|
||||
## How does this work ?
|
||||
|
||||
### [Struct information](https://github.com/Akilan1999/p2p-rendering-computation/blob/9d69aed8ce0fe5273aaff2828f7d51c3d5ac2ce4/generate/generate.go#L19)
|
||||
- ### ```Generate.go```:
|
||||
This file creates a local copy of P2PRC from where the CLI was called from.
|
||||
This go file also does various stuff like instruction of file should be ignored when copying and
|
||||
which of should not be. Now let's understand this. Below is a sample code which does the following:
|
||||
|
||||
```go
|
||||
//----------------------------------------------------------------
|
||||
// Action performed:
|
||||
// - Ensuring main.go file exists
|
||||
// - Skipping all .go files apart from the ones listed above
|
||||
// - Skipping .idea/ directory
|
||||
// - Skipping Makefile file
|
||||
//----------------------------------------------------------------
|
||||
Options.Skip = func(src string) (bool, error) {
|
||||
switch {
|
||||
case strings.HasSuffix(src, "main.go"):
|
||||
return false, nil
|
||||
case strings.HasSuffix(src, ".go"):
|
||||
return true, nil
|
||||
case strings.HasSuffix(src, ".idea"):
|
||||
return true, nil
|
||||
case strings.HasSuffix(src, "Makefile"):
|
||||
return true, nil
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Doing the copy
|
||||
err = copy.Copy("<P2PRC folder you want to copy from>", "<PATH to the directory>", Options)
|
||||
```
|
||||
|
||||
Unfortunately currently this will have to be manually edited in the ```Generate.go``` file. When using the generate
|
||||
module the user also creates their own Go module which is the modified version of P2PRC. This means
|
||||
if the 1 modified package is using another modified package then the appropriate import have to be modified
|
||||
in the file where the import is called:
|
||||
|
||||
Ex:
|
||||
```go
|
||||
//Sample Project module name = Test
|
||||
//Package names:
|
||||
//- Test/Genius
|
||||
//- Test/GeGeGenuis
|
||||
//
|
||||
// When we call the generate function with the new project with the module name = MicDrop
|
||||
// The new package name would be:
|
||||
// - MicDrop/Genius
|
||||
// - MicDrop/GeGeGenuis
|
||||
|
||||
// Test/Genius code depends on the package Test/GeGeGenuis
|
||||
import (
|
||||
"Test/GeGeGenuis"
|
||||
)
|
||||
|
||||
// When we create a new module with the copy of the
|
||||
// existing project we need change:
|
||||
import (
|
||||
"MicDrop/GeGeGenuis"
|
||||
)
|
||||
```
|
||||
|
||||
To do this we have built functions which can modify import names in the Go file provided.
|
||||
To customize the use case of your generate module you would need to manually add your own
|
||||
imports which are supposed to be replaced and in which files they are supposed to be replaced
|
||||
in.
|
||||
|
||||
```go
|
||||
// 1.0 - Test/Genius.go -> GeGeGenuis module
|
||||
// a is struct of type NewProject
|
||||
a.FileNameAST = "<path to project to copy from>/Test/Genius.go"
|
||||
// Get AST information of the file
|
||||
err := a.GetASTGoFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Change the appropriate Go file
|
||||
err = a.ChangeImports("Test/GeGeGenuis", "MicDrop/GeGeGenuis")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Writes the change to the appropriate file
|
||||
err = a.WriteGoAst()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
Higher order of execution of ```Generate.go```:
|
||||
1. Copy entire P2PRC project and ignores files which are not meant to be copied
|
||||
2. The folder name will be based on the new project name and the module name based on the new
|
||||
module name provided.
|
||||
3. Modifies the appropriate imports in the project as instructed in the code.
|
||||
4. Creates a commit with the new changes in the new project.
|
||||
|
||||
|
||||
- ### ``` modifyGenerate.go```:
|
||||
This a really simple implementation where we replace the imports
|
||||
in certain files as instructed from ```generate.go```. To do we create an AST (i.e Abstract Syntax tree)
|
||||
from new file we want to change the imports in. AST create a tree structure of expression. To change the
|
||||
import we can just traverse to the appropriate expression and change the value of that expression in
|
||||
the case of modifying imports. This approach is more simple than using templates.
|
||||
|
||||
|
||||
@@ -15,4 +15,6 @@ the project is git.sr.ht/~akilan1999/p2p-rendering-computation.
|
||||
## [Config Module](ConfigImplementation.md)
|
||||
## [Server Module](ServerImplementation.md)
|
||||
## [Client Module](ClientImplementation.md)
|
||||
## [P2P Module](P2PImplementation.md)
|
||||
## [P2P Module](P2PImplementation.md)
|
||||
## [Plugin Module](PluginImplementation.md)
|
||||
## [Generate Module](GenerateImplementation.md)
|
||||
@@ -32,7 +32,14 @@ into a single binary
|
||||
make install
|
||||
```
|
||||
|
||||
### Add appropriate paths to .bashrc
|
||||
#### For Windows
|
||||
To set up P2PRC on Windows, simply run this batch file.
|
||||
**Make sure you are not in admin mode when running this.**
|
||||
```
|
||||
.\install.bat
|
||||
```
|
||||
|
||||
### Add appropriate paths to .bashrc
|
||||
```
|
||||
export P2PRC=/<PATH>/p2p-rendering-computation
|
||||
export PATH=/<PATH>/p2p-rendering-computation:${PATH}
|
||||
@@ -64,22 +71,25 @@ COMMANDS:
|
||||
help, h Shows a list of commands or help for one command
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
--Server, -s Starts server (default: false) [$SERVER]
|
||||
--UpdateServerList, --us Update List of Server available based on servers iptables (default: false) [$UPDATE_SERVER_LIST]
|
||||
--ListServers, --ls List servers which can render tasks (default: false) [$LIST_SERVERS]
|
||||
--AddServer value, --as value Adds server IP address to iptables [$ADD_SERVER]
|
||||
--ViewImages value, --vi value View images available on the server IP address [$VIEW_IMAGES]
|
||||
--CreateVM value, --touch value Creates Docker container on the selected server [$CREATE_VM]
|
||||
--ContainerName value, --cn value Specifying the container run on the server side [$CONTAINER_NAME]
|
||||
--RemoveVM value, --rm value Stop and Remove Docker container [$REMOVE_VM]
|
||||
--ID value, --id value Docker Container ID [$ID]
|
||||
--Ports value, -p value Number of ports to open for the Docker Container [$NUM_PORTS]
|
||||
--GPU, --gpu Create Docker Containers to access GPU (default: false) [$USE_GPU]
|
||||
--Specification value, --specs value Specs of the server node [$SPECS]
|
||||
--SetDefaultConfig, --dc Sets a default configuration file (default: false) [$SET_DEFAULT_CONFIG]
|
||||
--NetworkInterfaces, --ni Shows the network interface in your computer (default: false) [$NETWORK_INTERFACE]
|
||||
--help, -h show help (default: false)
|
||||
--version, -v print the version (default: false)
|
||||
--Server, -s Starts server (default: false) [$SERVER]
|
||||
--UpdateServerList, --us Update List of Server available based on servers iptables (default: false) [$UPDATE_SERVER_LIST]
|
||||
--ListServers, --ls List servers which can render tasks (default: false) [$LIST_SERVERS]
|
||||
--AddServer value, --as value Adds server IP address to iptables [$ADD_SERVER]
|
||||
--ViewImages value, --vi value View images available on the server IP address [$VIEW_IMAGES]
|
||||
--CreateVM value, --touch value Creates Docker container on the selected server [$CREATE_VM]
|
||||
--ContainerName value, --cn value Specifying the container run on the server side [$CONTAINER_NAME]
|
||||
--RemoveVM value, --rm value Stop and Remove Docker container [$REMOVE_VM]
|
||||
--ID value, --id value Docker Container ID [$ID]
|
||||
--Ports value, -p value Number of ports to open for the Docker Container [$NUM_PORTS]
|
||||
--GPU, --gpu Create Docker Containers to access GPU (default: false) [$USE_GPU]
|
||||
--Specification value, --specs value Specs of the server node [$SPECS]
|
||||
--SetDefaultConfig, --dc Sets a default configuration file (default: false) [$SET_DEFAULT_CONFIG]
|
||||
--NetworkInterfaces, --ni Shows the network interface in your computer (default: false) [$NETWORK_INTERFACE]
|
||||
--ViewPlugins, --vp Shows plugins available to be executed (default: false) [$VIEW_PLUGIN]
|
||||
--TrackedContainers, --tc View containers which have been created from the client side (default: false) [$TRACKED_CONTAINERS]
|
||||
--ExecutePlugin value, --plugin value Plugin which needs to be executed [$EXECUTE_PLUGIN]
|
||||
--help, -h show help (default: false)
|
||||
--version, -v print the version (default: false)
|
||||
```
|
||||
|
||||
<br>
|
||||
@@ -88,7 +98,7 @@ GLOBAL OPTIONS:
|
||||
|
||||
<br>
|
||||
|
||||
# Using the Cli commands
|
||||
# Using basic commands
|
||||
|
||||
### Start as a server
|
||||
Do ensure you have docker installed for this
|
||||
@@ -96,7 +106,7 @@ Do ensure you have docker installed for this
|
||||
p2prc -s
|
||||
```
|
||||
|
||||
### View server Speciafication
|
||||
### View server Specification
|
||||
```
|
||||
p2prc --specs=<ip address>
|
||||
```
|
||||
@@ -133,3 +143,90 @@ p2prc --ls
|
||||
p2prc --ni
|
||||
```
|
||||
|
||||
### Viewing Containers created Client side
|
||||
```
|
||||
p2prc --tc
|
||||
```
|
||||
[read more on tracking containers](ClientImplementation.md#tracking-containers)
|
||||
|
||||
### Running plugin
|
||||
```
|
||||
p2prc --plugin <plugin name> --id <container id or group id>
|
||||
```
|
||||
|
||||
### Create group
|
||||
```
|
||||
p2prc --cgroup
|
||||
```
|
||||
### Add container to group
|
||||
```
|
||||
p2prc --group <group id> --id <container id>
|
||||
```
|
||||
### View groups
|
||||
```
|
||||
p2prc --groups
|
||||
```
|
||||
### View specific group
|
||||
```
|
||||
p2prc --group <group id>
|
||||
```
|
||||
### Delete container from group
|
||||
```
|
||||
p2prc --rmcgroup --group <group id> --id <container id>
|
||||
```
|
||||
### Delete entire group
|
||||
```
|
||||
p2prc --rmgroup <group id>
|
||||
```
|
||||
[read more on grouping containers](ClientImplementation.md#Grouping-Containers)
|
||||
### Extending usecase of P2PRC (Requires a go compiler to run)
|
||||
```
|
||||
p2prc --gen <project name> --mod <go module name>
|
||||
```
|
||||
[read more about the generate module](GenerateImplementation.md)
|
||||
|
||||
### Pulling plugin from a remote repo
|
||||
```
|
||||
p2prc --pp <repo link>
|
||||
```
|
||||
|
||||
### Deleting plugin from the plugin directory
|
||||
```
|
||||
p2prc --rp <plugin name>
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
--------------
|
||||
|
||||
<br>
|
||||
|
||||
# Using Plugins
|
||||
This feature is still Under Development:
|
||||
[Read more on the implementation](PluginImplementation.md)
|
||||
|
||||
#### Dependencies
|
||||
- Ansible:
|
||||
- Debian/ubuntu: ```sudo apt install ansible```
|
||||
- Others: [Installation link](https://ansible-tips-and-tricks.readthedocs.io/en/latest/ansible/install/)
|
||||
|
||||
#### Set ansible host_key_checking to false
|
||||
- On linux
|
||||
- ```sudo nano /etc/ansible/ansible.cfg```: Open the following file. If this file is not found then where
|
||||
ever the file ```ansible.cfg``` is located.
|
||||
- Add or uncomment ```host_key_checking = False```
|
||||
|
||||
#### Run Test Cases
|
||||
- Generate Test Case Ansible file
|
||||
- ```make testcases```
|
||||
- Enter inside plugin directory and run tests.
|
||||
Note: That docker needs to installed and needs to run without
|
||||
sudo. Refer the section install Docker.
|
||||
- ```cd plugin```
|
||||
- ```go test .```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ path of the IP table json file is received from the configuration module.
|
||||
"latency": "<latency>",
|
||||
"download": "<download>",
|
||||
"upload": "<upload>"
|
||||
"port no": "<server port no>"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
155
Docs/PluginImplementation.md
Normal file
155
Docs/PluginImplementation.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# Plugin Module Implementation
|
||||
## Topics
|
||||
1. [Introduciton](#introduction)
|
||||
2. [Site.yml](#site-File-Template)
|
||||
3. [Host](#hosts-file)
|
||||
4. [Description](#description-file)
|
||||
5. [Automatic port allocations](#automatic-port-allocations)
|
||||
6. [Sample plugins implemented](#sample-plugins-implemented)
|
||||
|
||||
## Introduction
|
||||
|
||||
The plugin module is designed to ensure clients can execute instructions in a declarative manner across different
|
||||
containers created. This means the user (i.e client) needs to write the instruction only once, and these instructions
|
||||
can be executed across different nodes in a repetitive manner.
|
||||
|
||||
In the scenario of this project Ansibles will be used as the way the users can create these instructions.
|
||||
|
||||
- [Setup instruction](Installation.md#Using-Plugins)
|
||||
|
||||
The plugin module introduces a new path to the config file known as pluginpath. This path by defaults points to
|
||||
```${P2PRC}/plugin/deploy```. Any file/folder inside ```plugin/deploy``` is part of the .gitginore. Plugins are
|
||||
detected by folder names inside the ```plugin/deploy```.
|
||||
```
|
||||
plugin
|
||||
|___ Deploy
|
||||
|___<plugin name>
|
||||
|___ site.yml
|
||||
|___ hosts
|
||||
|___ ports.json
|
||||
|___ description.txt
|
||||
.
|
||||
.
|
||||
.
|
||||
n: n number of plugins possible
|
||||
```
|
||||
|
||||
## Site File Template
|
||||
The site file is also known as the Ansible playbook and is incharge of executing
|
||||
instructions in a declarative manner. The below example specifies how to make one.
|
||||
```
|
||||
- hosts: all
|
||||
|
||||
tasks:
|
||||
- name: <task name>
|
||||
<ansible task>
|
||||
debug:
|
||||
msg: <debug message>
|
||||
```
|
||||
Read more about ansible tasks: https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html#about-playbooks
|
||||
|
||||
## Hosts file
|
||||
hosts file is also known as the inventory file. This file consists of all the information required to connect to other
|
||||
nodes to execute Ansible instructions. In this project this file needs to be set in a certain configuration because the
|
||||
go code or binary will populate this file automatically with the appropriate information required to connect to local or
|
||||
remote containers.
|
||||
|
||||
#### Note: Add as exactly specified below
|
||||
```
|
||||
all:
|
||||
vars:
|
||||
ansible_python_interpreter: /usr/bin/python3 // Path to your python 3 interpreter
|
||||
main:
|
||||
hosts:
|
||||
host1:
|
||||
// Note: These values will be automatically overwritten
|
||||
// by the Go functions
|
||||
ansible_host: 0.0.0.0
|
||||
ansible_port: 39269
|
||||
ansible_user: master
|
||||
ansible_ssh_pass: password
|
||||
ansible_sudo_pass: password
|
||||
```
|
||||
|
||||
## Ports.json
|
||||
The ```ports.json``` file is intended to mention the number of ports required
|
||||
by the plugin.
|
||||
|
||||
```
|
||||
{
|
||||
"NumOfPorts": <number of ports>
|
||||
}
|
||||
```
|
||||
|
||||
## Description file
|
||||
This is a simple text file used to describe what the module does.
|
||||
When the client is looking at various commands via the ClI.
|
||||
The description is displayed along-side the plugin name.
|
||||
|
||||
Ex: When the flag ```--ViewPlugins``` or ```--vp``` is called
|
||||
```
|
||||
{
|
||||
"PluginsDetected": [
|
||||
{
|
||||
"FolderName": "<name of the plugin>",
|
||||
"PluginDescription": "<description of the plugin>"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 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)
|
||||
|
||||
## Pull Plugins
|
||||
The following allows us to pull plugins from a remote git repository and store them
|
||||
in the default plugins directory. The implementation uses a Go git library to pull the
|
||||
git repo and automatically save it as a folder in the plugin path.
|
||||
|
||||
## Delete Plugins
|
||||
We delete the plugin folder based on the plugin name provided as an argument on the cli command.
|
||||
Once the folder is deleted, the plugin manager automatically knows that the plugin does not exist anymore.
|
||||
@@ -12,5 +12,7 @@
|
||||
3. [Server Module](ServerImplementation.md)
|
||||
4. [Config Module](ConfigImplementation.md)
|
||||
5. [Cli Module](CliImplementation.md)
|
||||
5. [Problems](Problems.md)
|
||||
6. [Plugin Module](PluginImplementation.md)
|
||||
7. [Generate Module](GenerateImplementation.md)
|
||||
5. [Problems](https://github.com/Akilan1999/p2p-rendering-computation/issues)
|
||||
|
||||
|
||||
@@ -159,6 +159,33 @@ it does not utilize server resources when it is not being used, or the task that
|
||||
To run this function all that is needed is the docker container ID. If the function is successful it returns
|
||||
a string that says success.
|
||||
|
||||
### Ports json file
|
||||
This file will help map internal ports inside a container to external ports inside a container. A common example
|
||||
would be the SSH port which is port 22 inside the docker container and is mapped to random TCP port outside container
|
||||
so that any external machines can directly connect into the container. The below representation mentions of where
|
||||
the ports.json file is located and also the format of that file.
|
||||
```
|
||||
|_ <Container name>
|
||||
|_ Dockerfile
|
||||
|_ description.txt
|
||||
|_ ports.json // The ports file
|
||||
```
|
||||
Format of the ports.json file
|
||||
```
|
||||
{
|
||||
"Port": [
|
||||
{
|
||||
"PortName": "<Port name>",
|
||||
"InternalPort": <internal port>,
|
||||
"Type": "<tcp/udp>",
|
||||
"ExternalPort": <external port>,
|
||||
"IsUsed": "<boolean value (i.e true or false)>",
|
||||
"Description": "<description about the port>"
|
||||
}, ... n
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
12
Makefile
12
Makefile
@@ -1,16 +1,10 @@
|
||||
SHELL := /bin/bash
|
||||
|
||||
install:
|
||||
go build -o p2prc
|
||||
echo '# Paths for p2p rendering and computation'
|
||||
echo 'export P2PRC=${PWD}'
|
||||
echo 'export PATH=${PWD}:$${PATH}'
|
||||
sh install.sh p2prc
|
||||
|
||||
build:
|
||||
go build -o p2prc
|
||||
|
||||
configfile:
|
||||
./p2prc --SetDefaultConfig
|
||||
testcases:
|
||||
sh plugin/generate_test_case.sh
|
||||
|
||||
run:
|
||||
go run main.go
|
||||
|
||||
56
README.md
56
README.md
@@ -4,6 +4,8 @@
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
<!-- seperator -->
|
||||
|
||||
|
||||
[](http://perso.crans.org/besson/LICENSE.html)
|
||||
[](https://GitHub.com/Akilan1999/p2p-rendering-computation/graphs/commit-activity)
|
||||
@@ -14,8 +16,8 @@ The main aim of this project was to create a custom peer to peer network. The us
|
||||
client has total flexibility on how to batch the tasks and the user acting as the server has complete
|
||||
flexibility on tracking the container's usages and killing the containers at any point of time.
|
||||
|
||||
## Demo
|
||||
[](https://www.youtube.com/watch?v=LRv3NR2lu7I "Simple P2P Cli application for creating containers")
|
||||
## Gophers talk
|
||||
[](https://www.youtube.com/watch?v=ovcZLEhQxWk "P2PRC - Gophers monthly talk")
|
||||
|
||||
<br>
|
||||
|
||||
@@ -41,26 +43,39 @@ This project aims to create a peer to peer (p2p) network, where a user can use t
|
||||
|
||||
<br>
|
||||
|
||||
## Installation
|
||||
## Installation from source
|
||||
1. Ensure the Go compiler is installed
|
||||
2. Ensure docker is installed
|
||||
```
|
||||
go version
|
||||
```
|
||||
3. Ensure docker is installed (Should run without sudo)
|
||||
```
|
||||
docker ps
|
||||
```
|
||||
3. Clone this repository
|
||||
```
|
||||
git clone https://github.com/Akilan1999/p2p-rendering-computation
|
||||
```
|
||||
4. Install and build the project
|
||||
```
|
||||
make install
|
||||
```
|
||||
```
|
||||
git clone https://github.com/Akilan1999/p2p-rendering-computation
|
||||
```
|
||||
4. Install and build the project
|
||||
```
|
||||
make install
|
||||
```
|
||||
- If you look closely you will get outputs such as:
|
||||
|
||||
// Add them to your .bashrc file
|
||||
export P2PRC=/<path>/p2p-rendering-computation
|
||||
export PATH=/<path>/p2p-rendering-computation:${PATH}
|
||||
|
||||
|
||||
5. Test if it works
|
||||
```
|
||||
p2prc -h
|
||||
```
|
||||
or
|
||||
```
|
||||
./p2prc -h
|
||||
```
|
||||
[Read more on the installation](Docs/Installation.md)
|
||||
```
|
||||
p2prc -h
|
||||
```
|
||||
or
|
||||
```
|
||||
./p2prc -h
|
||||
```
|
||||
[Read more on the installation and usage](Docs/Installation.md)
|
||||
|
||||
<br>
|
||||
|
||||
@@ -81,7 +96,6 @@ The programming language used for this project was Golang. The reason Go lang wa
|
||||
## Find out more
|
||||
As we are working on the open source project p2prc (i.e p2p network designed for computation).If you are interested in participating as a contributor
|
||||
or just providing feedback on new features to build or even just curious about new features added to the project. We have decided to create a discord group.
|
||||
Group:
|
||||
https://discord.gg/b4nRGTjYqy
|
||||
[](https://discord.gg/b4nRGTjYqy)
|
||||
|
||||
|
||||
|
||||
311
client/GroupTrackContainer.go
Normal file
311
client/GroupTrackContainer.go
Normal file
@@ -0,0 +1,311 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"git.sr.ht/~akilan1999/p2p-rendering-computation/config"
|
||||
"github.com/google/uuid"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Groups Data Structure type
|
||||
type Groups struct {
|
||||
GroupList []*Group `json:"Groups"`
|
||||
}
|
||||
|
||||
// Group Information about a single group
|
||||
type Group struct {
|
||||
ID string `json:"ID"`
|
||||
TrackContainerList []*TrackContainer `json:"TrackContainer"`
|
||||
// Sneaky as required only when removing the element
|
||||
// Set when GetGroup function is called
|
||||
index int
|
||||
}
|
||||
|
||||
// CreateGroup Creates a new group to add a set of track containers
|
||||
func CreateGroup() (*Group, error){
|
||||
// Creating variable of type new group
|
||||
var NewGroup Group
|
||||
// Generate new UUID for group ID
|
||||
id := uuid.New()
|
||||
// Add new group id and prepend with the string "grp"
|
||||
// The reason this is done is to differentiate between a
|
||||
// group ID and docker container ID
|
||||
NewGroup.ID = "grp" + id.String()
|
||||
// Adding the new group to the
|
||||
// GroupTrackContainer File
|
||||
err := NewGroup.AddGroupToFile()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &NewGroup,nil
|
||||
}
|
||||
|
||||
// RemoveGroup Removes group based on the group ID provided
|
||||
func RemoveGroup(GroupID string) error {
|
||||
// Read group information from the
|
||||
//grouptrackcontainer json file
|
||||
groups, err := ReadGroup()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Gets Group struct based on group ID
|
||||
// provided
|
||||
group, err := GetGroup(GroupID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Remove Group struct from the groups variable
|
||||
groups.GroupList = append(groups.GroupList[:group.index], groups.GroupList[group.index+1:]...)
|
||||
|
||||
// Write new groups to the grouptrackcontainer json file
|
||||
err = groups.WriteGroup()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddContainerToGroup Adds container information to the Group based on the Group ID
|
||||
func AddContainerToGroup(ContainerID string, GroupID string) (*Group, error) {
|
||||
// Gets container information based on container ID provided
|
||||
containerInfo, err := GetContainerInformation(ContainerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Gets group information based on the group ID provided
|
||||
group, err := GetGroup(GroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Adds container information the group
|
||||
group.AddContainer(containerInfo)
|
||||
|
||||
// Get Groups information from reading the grouptrackcontainer.json file
|
||||
groups, err := ReadGroup()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Updating specific element in the group list with the added container
|
||||
groups.GroupList[group.index] = group
|
||||
// Write groups information on the grouptrackcontainer.json file
|
||||
err = groups.WriteGroup()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return group, nil
|
||||
}
|
||||
|
||||
// RemoveContainerGroup Remove Container from the group ID specified
|
||||
func RemoveContainerGroup(ContainerID string, GroupID string) (*Group,error) {
|
||||
// Get container information based on container ID provided
|
||||
containerInfo, err := GetContainerInformation(ContainerID)
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
// Gets group information based on the group ID provided
|
||||
group, err := GetGroup(GroupID)
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
// Remove container from the appropriate group
|
||||
err = group.RemoveContainerGroup(containerInfo)
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
// Get Groups information from reading the grouptrackcontainer.json file
|
||||
groups, err := ReadGroup()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Updating specific element in the group list with the remove container
|
||||
groups.GroupList[group.index] = group
|
||||
// Write groups information on the grouptrackcontainer.json file
|
||||
err = groups.WriteGroup()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return group, nil
|
||||
}
|
||||
|
||||
// RemoveContainerGroups Remove Container from groups (i.e which ever groups has information
|
||||
// about that container). This is mostly called when a container is deleted or removed from
|
||||
// the tracked container list
|
||||
func RemoveContainerGroups(ContainerID string) error {
|
||||
// Get container information based on container ID provided
|
||||
containerInfo, err := GetContainerInformation(ContainerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Get Groups information from reading the grouptrackcontainer.json file
|
||||
groups, err := ReadGroup()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Removes container information from all groups it is found in
|
||||
err = groups.RemoveContainerGroups(containerInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Write groups information on the grouptrackcontainer.json file
|
||||
err = groups.WriteGroup()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetGroup Gets group information based on
|
||||
// group id provided
|
||||
func GetGroup(GroupID string) (*Group,error) {
|
||||
// Read group information from the
|
||||
//grouptrackcontainer json file
|
||||
groups, err := ReadGroup()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Iterate through the set of groups and
|
||||
// if the group ID matches then return it
|
||||
for i, group := range groups.GroupList {
|
||||
if group.ID == GroupID {
|
||||
group.index = i
|
||||
return group, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil,errors.New("Group not found. ")
|
||||
}
|
||||
|
||||
// AddGroupToFile Adds Group struct to the GroupTrackContainer File
|
||||
func (grp *Group) AddGroupToFile() error {
|
||||
// Gets all group information from the
|
||||
// GroupTrackContainer JSON file
|
||||
groups, err := ReadGroup()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Appending the newly created group
|
||||
groups.GroupList = append(groups.GroupList, grp)
|
||||
// Writing Group information to the GroupTrackContainer
|
||||
// JSON file
|
||||
err = groups.WriteGroup()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadGroup Function reads grouptrackcontainers.json and converts
|
||||
// result to Groups
|
||||
func ReadGroup() (*Groups,error) {
|
||||
// Get Path from config
|
||||
config, err := config.ConfigInit()
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
jsonFile, err := os.Open(config.GroupTrackContainersPath)
|
||||
// if we os.Open returns an error then handle it
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
// 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)
|
||||
// we initialize our Users array
|
||||
var groups Groups
|
||||
// we unmarshal our byteArray which contains our
|
||||
// jsonFile's content into 'users' which we defined above
|
||||
json.Unmarshal(byteValue, &groups)
|
||||
return &groups, nil
|
||||
}
|
||||
|
||||
|
||||
// WriteGroup Function to write type Groups to the grouptrackcontainers.json file
|
||||
func (grp *Groups)WriteGroup() error {
|
||||
file, err := json.MarshalIndent(grp, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Get Path from config
|
||||
config, err := config.ConfigInit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Writes to the appropriate file
|
||||
err = ioutil.WriteFile(config.GroupTrackContainersPath, file, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddContainer Adds a container to the Tracked container list of the group
|
||||
func (grp *Group)AddContainer(Container *TrackContainer) error {
|
||||
grp.TrackContainerList = append(grp.TrackContainerList, Container)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveContainerGroup Removes container information from the group
|
||||
func (grp *Group)RemoveContainerGroup(Container *TrackContainer) error {
|
||||
// Iterating through all container in the Group of Tracked Container
|
||||
for i, container := range grp.TrackContainerList {
|
||||
// If the container ID matches then remove the container from the group
|
||||
if container.Id == Container.Id {
|
||||
grp.TrackContainerList = append(grp.TrackContainerList[:i], grp.TrackContainerList[i+1:]...)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveContainerGroups removes container found in all groups
|
||||
func (grp *Groups)RemoveContainerGroups(Container *TrackContainer) error {
|
||||
// Iterating through all groups
|
||||
for i,group := range grp.GroupList {
|
||||
// Removes the container in the following group
|
||||
// if it exists
|
||||
err := group.RemoveContainerGroup(Container)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Set group information to list groups
|
||||
grp.GroupList[i] = group
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ModifyContainerGroups Modifies container information is all groups
|
||||
// available
|
||||
func (TC *TrackContainer)ModifyContainerGroups() error {
|
||||
group, err := ReadGroup()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Iterate though all groups and modify the container
|
||||
// information in groups where the modified container
|
||||
// ID matches
|
||||
for i, _ := range group.GroupList {
|
||||
// Checking in each group if the modified container ID exists
|
||||
for j, _:= range group.GroupList[i].TrackContainerList {
|
||||
// If there is match then change them
|
||||
if group.GroupList[i].TrackContainerList[j].Id == TC.Id {
|
||||
group.GroupList[i].TrackContainerList[j] = TC
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write modified result to the Groups track container JSON file
|
||||
err = group.WriteGroup()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
267
client/GroupTrackContainer_test.go
Normal file
267
client/GroupTrackContainer_test.go
Normal file
@@ -0,0 +1,267 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.sr.ht/~akilan1999/p2p-rendering-computation/server/docker"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Testing out if a new group is getting created
|
||||
func TestCreateGroup(t *testing.T) {
|
||||
group, err := CreateGroup()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
PrettyPrint(group)
|
||||
}
|
||||
|
||||
// Testing if the group gets removed when a
|
||||
// group ID is provided
|
||||
func TestRemoveGroup(t *testing.T) {
|
||||
// Creates a new group
|
||||
group, err := CreateGroup()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
// Removes the new group
|
||||
// it created
|
||||
err = RemoveGroup(group.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
// Testing if container information is added
|
||||
// to the created group
|
||||
func TestAddContainerToGroup(t *testing.T) {
|
||||
// Creates a new group
|
||||
group, err := CreateGroup()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Creating and adding the container to the
|
||||
// tracked list
|
||||
container1 ,err := docker.BuildRunContainer(0,"false","")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Testing the AddTrackContainer Function and adding the first container created
|
||||
err = AddTrackContainer(container1,"0.0.0.0")
|
||||
if err != nil {
|
||||
// Killing docker container created
|
||||
err = docker.StopAndRemoveContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Adds container information to the group
|
||||
Group, err := AddContainerToGroup(container1.ID,group.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
PrettyPrint(Group)
|
||||
|
||||
// Killing docker container created
|
||||
err = docker.StopAndRemoveContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Removing container 1 from the tracked list
|
||||
err = RemoveTrackedContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Removes the new group
|
||||
// it created
|
||||
err = RemoveGroup(group.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Testing if the container information is removed from the group
|
||||
func TestGroup_RemoveContainerGroup(t *testing.T) {
|
||||
// Creates a new group
|
||||
group, err := CreateGroup()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Creating and adding the container to the
|
||||
// tracked list
|
||||
container1 ,err := docker.BuildRunContainer(0,"false","")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Testing the AddTrackContainer Function and adding the first container created
|
||||
err = AddTrackContainer(container1,"0.0.0.0")
|
||||
if err != nil {
|
||||
// Killing docker container created
|
||||
err = docker.StopAndRemoveContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Adds container information to the group
|
||||
Group, err := AddContainerToGroup(container1.ID,group.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
fmt.Println("Container added")
|
||||
PrettyPrint(Group)
|
||||
|
||||
// Removing docker container from the group
|
||||
Group, err = RemoveContainerGroup(container1.ID,group.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
fmt.Println("Container removed")
|
||||
PrettyPrint(Group)
|
||||
|
||||
// Killing docker container created
|
||||
err = docker.StopAndRemoveContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Removing container 1 from the tracked list
|
||||
err = RemoveTrackedContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Removes the new group
|
||||
// it created
|
||||
err = RemoveGroup(group.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
// Testing that container are removed from all
|
||||
// created groups
|
||||
// Scenario:
|
||||
// - Create 2 groups
|
||||
// - Add Container information to each group
|
||||
// - Remove Container information from each group
|
||||
func TestGroups_RemoveContainerGroups(t *testing.T) {
|
||||
// Creates a new group
|
||||
group, err := CreateGroup()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
// Created another group assigned to variable group 1
|
||||
group1, err := CreateGroup()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Creating and adding the container to the
|
||||
// tracked list
|
||||
container1 ,err := docker.BuildRunContainer(0,"false","")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Testing the AddTrackContainer Function and adding the first container created
|
||||
err = AddTrackContainer(container1,"0.0.0.0")
|
||||
if err != nil {
|
||||
// Killing docker container created
|
||||
err = docker.StopAndRemoveContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Adds container information to the group
|
||||
Group, err := AddContainerToGroup(container1.ID,group.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
fmt.Println("Container added")
|
||||
PrettyPrint(Group)
|
||||
|
||||
// Adds container information to the group
|
||||
Group1, err := AddContainerToGroup(container1.ID,group1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
fmt.Println("Container added")
|
||||
PrettyPrint(Group1)
|
||||
|
||||
// Removing docker container from the group
|
||||
err = RemoveContainerGroups(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Killing docker container created
|
||||
err = docker.StopAndRemoveContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Removing container 1 from the tracked list
|
||||
err = RemoveTrackedContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Removes the new group
|
||||
// it created
|
||||
err = RemoveGroup(group.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Removes the new group
|
||||
// it created
|
||||
err = RemoveGroup(group1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
// UpdateIpTable Does the following to update it's IP table
|
||||
func UpdateIpTable(IpAddress string) error {
|
||||
func UpdateIpTable(IpAddress string, serverPort string) error {
|
||||
|
||||
config, err := config.ConfigInit()
|
||||
if err != nil {
|
||||
@@ -22,16 +22,17 @@ func UpdateIpTable(IpAddress string) error {
|
||||
|
||||
client := http.Client{}
|
||||
|
||||
|
||||
var resp []byte
|
||||
|
||||
version := p2p.Ip4or6(IpAddress)
|
||||
if version == "version 6" {
|
||||
resp, err = UploadMultipartFile(client,"http://["+IpAddress+"]:8088/IpTable","json",config.IPTable)
|
||||
resp, err = UploadMultipartFile(client,"http://[" + IpAddress + "]:" + serverPort + "/IpTable","json",config.IPTable)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
resp, err = UploadMultipartFile(client,"http://"+IpAddress+":8088/IpTable","json",config.IPTable)
|
||||
resp, err = UploadMultipartFile(client,"http://" + IpAddress + ":" + serverPort + "/IpTable","json",config.IPTable)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -114,9 +115,9 @@ func UpdateIpTableListClient() error {
|
||||
//}
|
||||
|
||||
if Addresses.IpAddress[j].Ipv6 != "" {
|
||||
err = UpdateIpTable(Addresses.IpAddress[j].Ipv6)
|
||||
err = UpdateIpTable(Addresses.IpAddress[j].Ipv6, Addresses.IpAddress[j].ServerPort)
|
||||
} else {
|
||||
err = UpdateIpTable(Addresses.IpAddress[j].Ipv4)
|
||||
err = UpdateIpTable(Addresses.IpAddress[j].Ipv4, Addresses.IpAddress[j].ServerPort)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -15,6 +15,13 @@ import (
|
||||
func GetSpecs(IP string)(*server.SysInfo,error) {
|
||||
var URL string
|
||||
version := p2p.Ip4or6(IP)
|
||||
|
||||
//Get port number of the server
|
||||
serverPort, err := GetServerPort(IP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if version == "version 6" {
|
||||
URL = "http://[" + IP + "]:" + serverPort + "/server_info"
|
||||
} else {
|
||||
|
||||
220
client/TrackContainers.go
Normal file
220
client/TrackContainers.go
Normal file
@@ -0,0 +1,220 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.sr.ht/~akilan1999/p2p-rendering-computation/config"
|
||||
"git.sr.ht/~akilan1999/p2p-rendering-computation/server/docker"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
// TrackContainers This struct stores arrays of current containers running
|
||||
type TrackContainers struct {
|
||||
TrackContainerList []TrackContainer `json:"TrackContainer"`
|
||||
}
|
||||
|
||||
// TrackContainer Stores information of current containers
|
||||
type TrackContainer struct {
|
||||
Id string `json:"ID"`
|
||||
Container *docker.DockerVM `json:"Container"`
|
||||
IpAddress string `json:"IpAddress"`
|
||||
}
|
||||
|
||||
// AddTrackContainer Adds new container which has been added to the track container
|
||||
func AddTrackContainer(d *docker.DockerVM,ipAddress string) error {
|
||||
// Checking if pointer d is null
|
||||
if d == nil {
|
||||
return errors.New("d is nil")
|
||||
}
|
||||
//Get config information to derive paths for track containers json file
|
||||
config,err := config.ConfigInit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Getting information about the file trackcontainers.json file
|
||||
stat, err := os.Stat(config.TrackContainersPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Initialize variable for TrackContainers
|
||||
var trackContainers TrackContainers
|
||||
// If the trackcontainers.json file is not empty then
|
||||
// Read from that file
|
||||
if stat.Size() != 0 {
|
||||
// Reads tracked container file
|
||||
trackContainersFile, err := ReadTrackContainers(config.TrackContainersPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
trackContainers = *trackContainersFile
|
||||
}
|
||||
|
||||
// Initialize new variable with type struct TrackContainers and
|
||||
// add container struct and ip address
|
||||
var trackContainer TrackContainer
|
||||
trackContainer.Id = d.ID
|
||||
trackContainer.Container = d
|
||||
trackContainer.IpAddress = ipAddress
|
||||
|
||||
// Adds new container as passed in the parameter to the struct
|
||||
if &trackContainer == nil {
|
||||
return errors.New("trackContainer variable is nil")
|
||||
}
|
||||
trackContainers.TrackContainerList = append(trackContainers.TrackContainerList, trackContainer)
|
||||
|
||||
// write modified information to the tracked json file
|
||||
data,err := json.MarshalIndent(trackContainers, "", "\t")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(config.TrackContainersPath,data,0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveTrackedContainer This function removos tracked container from the trackcontainer JSON file
|
||||
func RemoveTrackedContainer(id string) error {
|
||||
//Get config information to derive paths for track containers json file
|
||||
config,err := config.ConfigInit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Getting tracked container struct
|
||||
trackedContainers, err := ReadTrackContainers(config.TrackContainersPath)
|
||||
// Storing index of element to remove
|
||||
var removeElement int
|
||||
removeElement = -1
|
||||
for i := range trackedContainers.TrackContainerList {
|
||||
if trackedContainers.TrackContainerList[i].Id == id {
|
||||
removeElement = i
|
||||
break
|
||||
}
|
||||
}
|
||||
// Checks if the element to be removed has been detected
|
||||
if removeElement == -1 {
|
||||
return errors.New("Container ID not found in the tracked list")
|
||||
}
|
||||
// Remove the detected element from the struct
|
||||
trackedContainers.TrackContainerList = append(trackedContainers.TrackContainerList[:removeElement], trackedContainers.TrackContainerList[removeElement+1:]...)
|
||||
|
||||
// write modified information to the tracked json file
|
||||
data,err := json.MarshalIndent(trackedContainers, "", "\t")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(config.TrackContainersPath,data,0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ViewTrackedContainers View Containers currently tracked
|
||||
func ViewTrackedContainers() (error,*TrackContainers) {
|
||||
config,err := config.ConfigInit()
|
||||
if err != nil {
|
||||
return err,nil
|
||||
}
|
||||
trackedContianers, err := ReadTrackContainers(config.TrackContainersPath)
|
||||
if err != nil {
|
||||
return err,nil
|
||||
}
|
||||
|
||||
return nil,trackedContianers
|
||||
}
|
||||
|
||||
// ReadTrackContainers Reads containers which are currently tracked
|
||||
func ReadTrackContainers(filename string) (*TrackContainers, error) {
|
||||
buf, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &TrackContainers{}
|
||||
err = json.Unmarshal(buf, c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("in file %q: %v", filename, err)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
//func ModifyTrackContainers()
|
||||
|
||||
// GetContainerInformation gets information about container based on
|
||||
// container ID provided
|
||||
func GetContainerInformation(ID string) (*TrackContainer, error) {
|
||||
// Getting the current containers
|
||||
err, CurrentContainers := ViewTrackedContainers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Iterating through all tracked containers to get the container information
|
||||
// of the ID passed through the function parameter
|
||||
for _, container := range CurrentContainers.TrackContainerList {
|
||||
if container.Container.ID == ID {
|
||||
return &container, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("Container not found. ")
|
||||
}
|
||||
|
||||
// ModifyContainerInformation Modifies information inside the container
|
||||
func (TC *TrackContainer)ModifyContainerInformation() error {
|
||||
// Gets all the information of tracker containers
|
||||
err, t := ViewTrackedContainers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Find the element where the containers match and
|
||||
// change them
|
||||
for i, container := range t.TrackContainerList {
|
||||
if TC.Id == container.Id {
|
||||
t.TrackContainerList[i] = *TC
|
||||
break
|
||||
}
|
||||
}
|
||||
// Write the modified information to the file
|
||||
// write modified information to the tracked json file
|
||||
err = t.WriteContainers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteContainers Write information back to the config file
|
||||
func (TC *TrackContainers)WriteContainers() error {
|
||||
// Initialize config file
|
||||
config,err := config.ConfigInit()
|
||||
// write modified information to the tracked json file
|
||||
data,err := json.MarshalIndent(TC, "", "\t")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(config.TrackContainersPath,data,0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckID Checks if the ID belongs to a group or a single container
|
||||
func CheckID(ID string) (string,error) {
|
||||
// For group checks if the 1st characters is "grp"
|
||||
if ID[0:3] == "grp" {
|
||||
return "group", nil
|
||||
} else {
|
||||
return "container", nil
|
||||
}
|
||||
return "",nil
|
||||
}
|
||||
120
client/TrackContianers_test.go
Normal file
120
client/TrackContianers_test.go
Normal file
@@ -0,0 +1,120 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.sr.ht/~akilan1999/p2p-rendering-computation/server/docker"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Tests a scenario where the container are getting tracked
|
||||
func TestAddTrackContainer(t *testing.T) {
|
||||
// Create docker container and get SSH port
|
||||
container1 ,err := docker.BuildRunContainer(0,"false","")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
// Testing the AddTrackContainer Function
|
||||
err = AddTrackContainer(container1,"0.0.0.0")
|
||||
if err != nil {
|
||||
// Killing docker container created
|
||||
err = docker.StopAndRemoveContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
// Killing docker container created
|
||||
err = docker.StopAndRemoveContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
// Testing the remove container function
|
||||
// NOTE: This test can also be considered as a whole flow on the process of
|
||||
// tracked containers
|
||||
func TestRemoveTrackedContainer(t *testing.T) {
|
||||
container1 ,err := docker.BuildRunContainer(0,"false","")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
container2 ,err := docker.BuildRunContainer(0,"false","")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Testing the AddTrackContainer Function and adding the first container created
|
||||
err = AddTrackContainer(container1,"0.0.0.0")
|
||||
if err != nil {
|
||||
// Killing docker container created
|
||||
err = docker.StopAndRemoveContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
// Killing docker container created
|
||||
err = docker.StopAndRemoveContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Testing the AddTrackContainer Function and the adding the second container created
|
||||
err = AddTrackContainer(container2,"0.0.0.0")
|
||||
if err != nil {
|
||||
// Killing docker container created
|
||||
err = docker.StopAndRemoveContainer(container2.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
// Killing docker container created
|
||||
err = docker.StopAndRemoveContainer(container2.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Removing container 1 from the tracked list
|
||||
err = RemoveTrackedContainer(container1.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Removing container 2 from the tracked list
|
||||
err = RemoveTrackedContainer(container2.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
// Test function that checks if the ID belongs to
|
||||
// a group or container running
|
||||
func TestCheckID(t *testing.T) {
|
||||
id := "grp123"
|
||||
checkID, err := CheckID(id)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Fail()
|
||||
}
|
||||
if checkID == "group" {
|
||||
fmt.Println("pass")
|
||||
} else {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
@@ -10,13 +10,11 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
var (
|
||||
serverPort = "8088"
|
||||
client = http.Client{}
|
||||
)
|
||||
|
||||
|
||||
var client = http.Client{}
|
||||
|
||||
// StartContainer Start container using REST api Implementation
|
||||
// From the selected server IP address
|
||||
// TODO: Test cases for this function
|
||||
@@ -25,6 +23,13 @@ func StartContainer(IP string, NumPorts int, GPU bool, ContainerName string) (*d
|
||||
// Passes URL with number of TCP ports to allocated and to give GPU access to the docker container
|
||||
var URL string
|
||||
version := p2p.Ip4or6(IP)
|
||||
|
||||
//Get port number of the server
|
||||
serverPort, err := GetServerPort(IP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if version == "version 6" {
|
||||
URL = "http://[" + IP + "]:" + serverPort + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) + "&ContainerName=" + ContainerName
|
||||
} else {
|
||||
@@ -51,6 +56,12 @@ func StartContainer(IP string, NumPorts int, GPU bool, ContainerName string) (*d
|
||||
return nil,err
|
||||
}
|
||||
|
||||
// Adds the container to the tracked list
|
||||
err = AddTrackContainer(&dockerResult, IP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &dockerResult, nil
|
||||
}
|
||||
|
||||
@@ -58,6 +69,13 @@ func StartContainer(IP string, NumPorts int, GPU bool, ContainerName string) (*d
|
||||
func RemoveContianer(IP string,ID string) error {
|
||||
var URL string
|
||||
version := p2p.Ip4or6(IP)
|
||||
|
||||
//Get port number of the server
|
||||
serverPort, err := GetServerPort(IP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if version == "version 6" {
|
||||
URL = "http://[" + IP + "]:" + serverPort + "/RemoveContainer?id=" + ID
|
||||
} else {
|
||||
@@ -74,9 +92,22 @@ func RemoveContianer(IP string,ID string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Checks if success is returned in the body
|
||||
if string(byteValue[:]) == "success" {
|
||||
fmt.Println("success")
|
||||
}
|
||||
|
||||
// Remove container from groups it exists in
|
||||
err = RemoveContainerGroups(ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Remove container created from the tracked list
|
||||
err = RemoveTrackedContainer(ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -85,6 +116,13 @@ func ViewContainers(IP string)(*docker.DockerContainers, error){
|
||||
// Passes URL with route /ShowImages
|
||||
var URL string
|
||||
version := p2p.Ip4or6(IP)
|
||||
|
||||
//Get port number of the server
|
||||
serverPort, err := GetServerPort(IP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if version == "version 6" {
|
||||
URL = "http://[" + IP + "]:" + serverPort + "/ShowImages"
|
||||
} else {
|
||||
@@ -113,20 +151,42 @@ func ViewContainers(IP string)(*docker.DockerContainers, error){
|
||||
return &Result, nil
|
||||
}
|
||||
|
||||
// PrintStartContainer Prints results Generated container
|
||||
func PrintStartContainer(d *docker.DockerVM){
|
||||
fmt.Println("ID : " + fmt.Sprint(d.ID))
|
||||
fmt.Println("SSH port: " + fmt.Sprint(d.SSHPort))
|
||||
fmt.Println("SSH username: " + fmt.Sprint(d.SSHUsername))
|
||||
fmt.Println("SSH password: " + fmt.Sprint(d.SSHPassword))
|
||||
fmt.Println("VNC port: " + fmt.Sprint(d.VNCPort))
|
||||
fmt.Println("VNC password: " + fmt.Sprint(d.VNCPassword))
|
||||
fmt.Println("Ports Open (All TCP ports):")
|
||||
for i := range d.Ports {
|
||||
fmt.Println(d.Ports[i])
|
||||
// GetServerPort Helper function to do find out server port information
|
||||
func GetServerPort(IpAddress string) (string,error) {
|
||||
// Getting information from the clients ip table
|
||||
ipTable, err := p2p.ReadIpTable()
|
||||
if err != nil {
|
||||
return "",err
|
||||
}
|
||||
|
||||
// Iterate thorough ip table struct and find
|
||||
// out which port is for the ip address provided
|
||||
// in the parameter of the function
|
||||
for _, address := range ipTable.IpAddress {
|
||||
// If we found a match then return a port
|
||||
if address.Ipv4 == IpAddress || address.Ipv6 == IpAddress {
|
||||
return address.ServerPort, nil
|
||||
}
|
||||
}
|
||||
|
||||
// We return default port
|
||||
return "8088",nil
|
||||
}
|
||||
|
||||
// PrintStartContainer Prints results Generated container
|
||||
//func PrintStartContainer(d *docker.DockerVM){
|
||||
// fmt.Println("ID : " + fmt.Sprint(d.ID))
|
||||
// fmt.Println("SSH port: " + fmt.Sprint(d.SSHPort))
|
||||
// fmt.Println("SSH username: " + fmt.Sprint(d.SSHUsername))
|
||||
// fmt.Println("SSH password: " + fmt.Sprint(d.SSHPassword))
|
||||
// fmt.Println("VNC port: " + fmt.Sprint(d.VNCPort))
|
||||
// fmt.Println("VNC password: " + fmt.Sprint(d.VNCPassword))
|
||||
// fmt.Println("Ports Open (All TCP ports):")
|
||||
// for i := range d.Ports {
|
||||
// fmt.Println(d.Ports[i])
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
// TODO implementation using RPC calls
|
||||
//func StartContainer(Ip string) (*docker.DockerVM,error){
|
||||
|
||||
167
cmd/action.go
167
cmd/action.go
@@ -4,7 +4,9 @@ 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/generate"
|
||||
"git.sr.ht/~akilan1999/p2p-rendering-computation/p2p"
|
||||
"git.sr.ht/~akilan1999/p2p-rendering-computation/plugin"
|
||||
"git.sr.ht/~akilan1999/p2p-rendering-computation/server"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@@ -22,12 +24,24 @@ var CliAction = func(ctx *cli.Context) error {
|
||||
if err != nil {
|
||||
fmt.Print(err)
|
||||
}
|
||||
|
||||
// Reads from ip table and passes it
|
||||
// on to struct print function
|
||||
//Servers, err := p2p.ReadIpTable()
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
//client.PrettyPrint(Servers)
|
||||
p2p.PrintIpTable()
|
||||
}
|
||||
|
||||
// Displays the IP table
|
||||
if ServerList {
|
||||
// Reads from ip table and passes it
|
||||
// on to struct print function
|
||||
//Servers, err := p2p.ReadIpTable()
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
p2p.PrintIpTable()
|
||||
}
|
||||
|
||||
@@ -50,6 +64,13 @@ var CliAction = func(ctx *cli.Context) error {
|
||||
} else {
|
||||
IpAddr.Ipv4 = AddServer
|
||||
}
|
||||
|
||||
// If a server port is provided then set it
|
||||
if Ports != "" {
|
||||
IpAddr.ServerPort = Ports
|
||||
} else {
|
||||
IpAddr.ServerPort = "8088"
|
||||
}
|
||||
// Append IP address to variable result which
|
||||
// is a list
|
||||
res.IpAddress = append(res.IpAddress, IpAddr)
|
||||
@@ -124,6 +145,150 @@ var CliAction = func(ctx *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
// If the view plugin flag is called then display all
|
||||
// plugins available
|
||||
if ViewPlugin {
|
||||
plugins ,err := plugin.DetectPlugins()
|
||||
if err != nil {
|
||||
fmt.Print(err)
|
||||
}
|
||||
client.PrettyPrint(plugins)
|
||||
}
|
||||
|
||||
// If the flag Tracked Container is called or the flag
|
||||
// --tc
|
||||
if TrackedContainers {
|
||||
err, trackedContainers := client.ViewTrackedContainers()
|
||||
if err != nil {
|
||||
fmt.Print(err)
|
||||
}
|
||||
client.PrettyPrint(trackedContainers)
|
||||
}
|
||||
|
||||
//Executing plugin when the plugin flag is called
|
||||
// --plugin
|
||||
if ExecutePlugin != "" {
|
||||
// To execute plugin requires the container ID or group ID provided when being executed
|
||||
if ID != "" {
|
||||
err := plugin.CheckRunPlugin(ExecutePlugin, ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
fmt.Println("Success")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("provide container ID")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Executing function to create new group
|
||||
// Creates new group and outputs JSON file
|
||||
if CreateGroup {
|
||||
group, err := client.CreateGroup()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client.PrettyPrint(group)
|
||||
}
|
||||
|
||||
// Actions to be performed when the
|
||||
// group flag is called
|
||||
// --group <Group ID>
|
||||
if Group != "" {
|
||||
// Remove container from group based on group ID provided
|
||||
// --rmcgroup --id <contianer id>
|
||||
if RemoveContainerGroup && ID != "" {
|
||||
group, err := client.RemoveContainerGroup(ID, Group)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
client.PrettyPrint(group)
|
||||
}
|
||||
} else if ID != "" { // Add container to group based on group ID provided
|
||||
// --id <Container ID>
|
||||
group, err := client.AddContainerToGroup(ID,Group)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
client.PrettyPrint(group)
|
||||
}
|
||||
} else { // View all information about current group
|
||||
group, err := client.GetGroup(Group)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
client.PrettyPrint(group)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Execute function to remove entire group
|
||||
// when remove group flag is called
|
||||
// --rmgroup
|
||||
if RemoveGroup != "" {
|
||||
err := client.RemoveGroup(RemoveGroup)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
fmt.Println("Group Removed")
|
||||
}
|
||||
}
|
||||
|
||||
// Execute Function to view all groups
|
||||
if Groups {
|
||||
groups, err := client.ReadGroup()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
client.PrettyPrint(groups)
|
||||
}
|
||||
}
|
||||
// -- REMOVE ON REGULAR RELEASE --
|
||||
// when flag --gen is called an extension
|
||||
// of the project is created to repurpose
|
||||
// the project for custom purpose
|
||||
if Generate != "" {
|
||||
var err error
|
||||
// If the module name is provided
|
||||
if Modulename != "" {
|
||||
err = generate.GenerateNewProject(Generate,Modulename)
|
||||
} else {
|
||||
err = generate.GenerateNewProject(Generate,Generate)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
fmt.Println("Created new folder: " + Generate)
|
||||
fmt.Println("1. Enter inside " + Generate + " directory")
|
||||
fmt.Println("2. git remote add " + Generate + " <PATH to the github repo>")
|
||||
fmt.Println("3. git push " + Generate + " <PATH to the github repo>")
|
||||
fmt.Println("4. go mod tidy")
|
||||
fmt.Println("5. sh install.sh " + Generate)
|
||||
fmt.Println("6. ./" + Generate + " -h (This is to test if the binary is working)")
|
||||
}
|
||||
}
|
||||
//--------------------------------
|
||||
|
||||
if PullPlugin != "" {
|
||||
err := plugin.DownloadPlugin(PullPlugin)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
fmt.Println("Success")
|
||||
}
|
||||
}
|
||||
|
||||
if RemovePlugin != "" {
|
||||
err := plugin.DeletePlugin(RemovePlugin)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
fmt.Println("Success")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
131
cmd/flags.go
131
cmd/flags.go
@@ -6,20 +6,35 @@ import (
|
||||
|
||||
// Variables declared for CLI
|
||||
var (
|
||||
AddServer string
|
||||
ViewImages string
|
||||
CreateVM string
|
||||
ContainerName string
|
||||
Ports string
|
||||
Server bool
|
||||
RemoveVM string
|
||||
ID string
|
||||
Specs string
|
||||
GPU bool
|
||||
UpdateServerList bool
|
||||
ServerList bool
|
||||
SetDefaultConfig bool
|
||||
NetworkInterface bool
|
||||
AddServer string
|
||||
ViewImages string
|
||||
CreateVM string
|
||||
ContainerName string
|
||||
Ports string
|
||||
Server bool
|
||||
RemoveVM string
|
||||
ID string
|
||||
Specs string
|
||||
GPU bool
|
||||
UpdateServerList bool
|
||||
ServerList bool
|
||||
SetDefaultConfig bool
|
||||
NetworkInterface bool
|
||||
ViewPlugin bool
|
||||
TrackedContainers bool
|
||||
ExecutePlugin string
|
||||
CreateGroup bool
|
||||
Group string
|
||||
Groups bool
|
||||
RemoveContainerGroup bool
|
||||
RemoveGroup string
|
||||
// Generate only allowed in dev release
|
||||
// -- REMOVE ON REGULAR RELEASE --
|
||||
Generate string
|
||||
Modulename string
|
||||
//--------------------------------
|
||||
PullPlugin string
|
||||
RemovePlugin string
|
||||
)
|
||||
|
||||
var AppConfigFlags = []cli.Flag{
|
||||
@@ -122,4 +137,92 @@ var AppConfigFlags = []cli.Flag{
|
||||
EnvVars: []string{"NETWORK_INTERFACE"},
|
||||
Destination: &NetworkInterface,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "ViewPlugins",
|
||||
Aliases: []string{"vp"},
|
||||
Usage: "Shows plugins available to be executed",
|
||||
EnvVars: []string{"VIEW_PLUGIN"},
|
||||
Destination: &ViewPlugin,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "TrackedContainers",
|
||||
Aliases: []string{"tc"},
|
||||
Usage: "View containers which have " +
|
||||
"been created from the client side ",
|
||||
EnvVars: []string{"TRACKED_CONTAINERS"},
|
||||
Destination: &TrackedContainers,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ExecutePlugin",
|
||||
Aliases: []string{"plugin"},
|
||||
Usage: "Plugin which needs to be executed",
|
||||
EnvVars: []string{"EXECUTE_PLUGIN"},
|
||||
Destination: &ExecutePlugin,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "CreateGroup",
|
||||
Aliases: []string{"cgroup"},
|
||||
Usage: "Creates a new group",
|
||||
EnvVars: []string{"CREATE_GROUP"},
|
||||
Destination: &CreateGroup,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "Group",
|
||||
Aliases: []string{"group"},
|
||||
Usage: "group flag with argument group ID",
|
||||
EnvVars: []string{"GROUP"},
|
||||
Destination: &Group,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "Groups",
|
||||
Aliases: []string{"groups"},
|
||||
Usage: "View all groups",
|
||||
EnvVars: []string{"GROUPS"},
|
||||
Destination: &Groups,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "RemoveContainerGroup",
|
||||
Aliases: []string{"rmcgroup"},
|
||||
Usage: "Remove specific container in the group",
|
||||
EnvVars: []string{"REMOVE_CONTAINER_GROUP"},
|
||||
Destination: &RemoveContainerGroup,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "RemoveGroup",
|
||||
Aliases: []string{"rmgroup"},
|
||||
Usage: "Removes the entire group",
|
||||
EnvVars: []string{"REMOVE_GROUP"},
|
||||
Destination: &RemoveGroup,
|
||||
},
|
||||
// Generate only allowed in dev release
|
||||
// -- REMOVE ON REGULAR RELEASE --
|
||||
&cli.StringFlag{
|
||||
Name: "Generate",
|
||||
Aliases: []string{"gen"},
|
||||
Usage: "Generates a new copy of P2PRC which can be modified based on your needs",
|
||||
EnvVars: []string{"GENERATE"},
|
||||
Destination: &Generate,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ModuleName",
|
||||
Aliases: []string{"mod"},
|
||||
Usage: "New go project module name",
|
||||
EnvVars: []string{"MODULENAME"},
|
||||
Destination: &Modulename,
|
||||
},
|
||||
//--------------------------------
|
||||
&cli.StringFlag{
|
||||
Name: "PullPlugin",
|
||||
Aliases: []string{"pp"},
|
||||
Usage: "Pulls plugin from git repos",
|
||||
EnvVars: []string{"PULLPLUGIN"},
|
||||
Destination: &PullPlugin,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "RemovePlugin",
|
||||
Aliases: []string{"rp"},
|
||||
Usage: "Removes plugin",
|
||||
EnvVars: []string{"REMOVEPLUGIN"},
|
||||
Destination: &RemovePlugin,
|
||||
},
|
||||
}
|
||||
@@ -8,24 +8,24 @@ import (
|
||||
|
||||
var (
|
||||
defaultPath string
|
||||
defaults = map[string]interface{}{
|
||||
"IPTable": "/etc/p2p-rendering/ip_table.json",
|
||||
"DockerContainers": "/home/akilan/Documents/p2prendering/p2p-redering-computation/server/docker/containers/",
|
||||
"DefaultDockerFile": "/home/akilan/Documents/p2prendering/p2p-redering-computation/server/docker/containers/docker-ubuntu-sshd/",
|
||||
"SpeedTestFile":"/etc/p2p-rendering/50.bin",
|
||||
}
|
||||
defaults = map[string]interface{}{}
|
||||
configName = "config"
|
||||
configType = "json"
|
||||
configFile = "config.json"
|
||||
configPaths []string
|
||||
defaultEnvName = "P2PRC"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
IPTable string
|
||||
DockerContainers string
|
||||
DefaultDockerFile string
|
||||
SpeedTestFile string
|
||||
IPV6Address string
|
||||
IPTable string
|
||||
DockerContainers string
|
||||
DefaultDockerFile string
|
||||
SpeedTestFile string
|
||||
IPV6Address string
|
||||
PluginPath string
|
||||
TrackContainersPath string
|
||||
ServerPort string
|
||||
GroupTrackContainersPath string
|
||||
//NetworkInterface string
|
||||
//NetworkInterfaceIPV6Index int
|
||||
}
|
||||
@@ -63,18 +63,52 @@ func Copy(src, dst string) error {
|
||||
return out.Close()
|
||||
}
|
||||
|
||||
// GetPathP2PRC Getting P2PRC Directory from environment variable
|
||||
func GetPathP2PRC()(string,error) {
|
||||
curDir := os.Getenv(defaultEnvName)
|
||||
return curDir + "/", nil
|
||||
}
|
||||
|
||||
// SetEnvName Sets the environment name
|
||||
// This is to ensure that the Path of your project is detected from
|
||||
// your environment variable
|
||||
// This is useful when extending the use case of P2PRC
|
||||
func SetEnvName(EnvName string) error {
|
||||
defaultEnvName = EnvName
|
||||
// Handling error to be implemented only if needed
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetCurrentPath Getting P2PRC Directory from environment variable
|
||||
func GetCurrentPath()(string,error) {
|
||||
curDir := os.Getenv("PWD")
|
||||
return curDir + "/", nil
|
||||
}
|
||||
|
||||
|
||||
// SetDefaults This function to be called only during a
|
||||
// make install
|
||||
func SetDefaults() error {
|
||||
//Getting Current Directory from environment variable
|
||||
curDir := os.Getenv("P2PRC")
|
||||
|
||||
//Setting current directory to default path
|
||||
defaultPath = curDir + "/"
|
||||
defaultPath, err := GetPathP2PRC()
|
||||
if err != nil{
|
||||
return err
|
||||
}
|
||||
|
||||
//Create ip_table.json in the json directory
|
||||
err := Copy("p2p/ip_table.json","p2p/iptable/ip_table.json")
|
||||
//Creates ip_table.json in the json directory
|
||||
err = Copy("p2p/ip_table.json","p2p/iptable/ip_table.json")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//Creates a copy of trackcontainers.json in the appropriate directory
|
||||
err = Copy("client/trackcontainers.json","client/trackcontainers/trackcontainers.json")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//Creates a copy of trackcontainers.json in the appropriate directory
|
||||
err = Copy("client/grouptrackcontainers.json","client/trackcontainers/grouptrackcontainers.json")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -86,6 +120,10 @@ func SetDefaults() error {
|
||||
defaults["DockerContainers"] = defaultPath + "server/docker/containers/"
|
||||
defaults["SpeedTestFile"] = defaultPath + "p2p/50.bin"
|
||||
defaults["IPV6Address"] = ""
|
||||
defaults["PluginPath"] = defaultPath + "plugin/deploy"
|
||||
defaults["TrackContainersPath"] = defaultPath + "client/trackcontainers/trackcontainers.json"
|
||||
defaults["GroupTrackContainersPath"] = defaultPath + "client/trackcontainers/grouptrackcontainers.json"
|
||||
defaults["ServerPort"] = "8088"
|
||||
//defaults["NetworkInterface"] = "wlp0s20f3"
|
||||
//defaults["NetworkInterfaceIPV6Index"] = "2"
|
||||
|
||||
@@ -109,9 +147,11 @@ func SetDefaults() error {
|
||||
|
||||
func ConfigInit()(*Config,error) {
|
||||
|
||||
curDir := os.Getenv("P2PRC")
|
||||
//Setting current directory to default path
|
||||
defaultPath = curDir + "/"
|
||||
defaultPath, err := GetPathP2PRC()
|
||||
if err != nil{
|
||||
return nil, err
|
||||
}
|
||||
//Paths to search for config file
|
||||
configPaths = append(configPaths, defaultPath)
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -17,3 +19,45 @@ func TestSetDefaults(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCurrentPath(t *testing.T) {
|
||||
path, err := GetCurrentPath()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
fmt.Println(path)
|
||||
}
|
||||
|
||||
func TestGetPathP2PRC(t *testing.T) {
|
||||
path, err := GetPathP2PRC()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
fmt.Println(path)
|
||||
}
|
||||
|
||||
func TestSetEnvName(t *testing.T) {
|
||||
// Create an Env variable TEST with the value "lol"
|
||||
err := os.Setenv("TEST", "lol")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
// Sets the environment variable as the default to read
|
||||
// for P2PRC
|
||||
err = SetEnvName("TEST")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Checks if the output for the default read is "lol"
|
||||
path, err := GetPathP2PRC()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
fmt.Println(path)
|
||||
}
|
||||
201
deploy/LICENSE
201
deploy/LICENSE
@@ -1,201 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
148
deploy/README.md
148
deploy/README.md
@@ -1,148 +0,0 @@
|
||||
# Ansible p2p-rendering-computation
|
||||
### Modified from:
|
||||
|
||||
This repository contains an Ansible playbook and instructions to create and manage a single (or many) bare metal deep learning machines. For a description of why Ansible was chosen and what other alternatives were considered, please see [ToolSelection.md](ToolSelection.md)
|
||||
|
||||
## Quick Reference
|
||||
|
||||
If you've already [installed Ansible](#Installation), you can execute the entire playbook by running:
|
||||
|
||||
```bash
|
||||
$ ansible-playbook packages.yml
|
||||
```
|
||||
|
||||
You can also execute only the pieces you need by passing tags on the command line:
|
||||
|
||||
- Install only apt/pip [pre-requisites](roles/packages) to execute the other roles:
|
||||
```bash
|
||||
$ ansible-playbook packages.yml --tags "packages"
|
||||
```
|
||||
- Install [Docker CE](roles/docker):
|
||||
```bash
|
||||
$ ansible-playbook packages.yml --tags "docker"
|
||||
```
|
||||
- Install the [Nvidia CUDA GPU drivers](roles/cuda):
|
||||
```bash
|
||||
$ ansible-playbook packages.yml --tags "cuda"
|
||||
```
|
||||
- Install the [Nvidia Docker Runtime](roles/nvidia):
|
||||
```bash
|
||||
$ ansible-playbook packages.yml --tags "nvidia"
|
||||
```
|
||||
|
||||
## What's Included
|
||||
|
||||
After running the ansible script your machines will be loaded with the following:
|
||||
|
||||
1. Docker
|
||||
2. Nvidia CUDA GPU Drivers
|
||||
3. Nvidia Docker Runtime
|
||||
4. TensorFlow GPU Python3 Docker Container
|
||||
5. JupyterLab
|
||||
|
||||
## Using This Repository to Configure Your Environment
|
||||
|
||||
1. [Installation](#Installation)
|
||||
2. [Configuration](#Configuration)
|
||||
3. [Running](#Running)
|
||||
|
||||
---
|
||||
|
||||
### Installation
|
||||
|
||||
Ansible runs on your local machine and sends commands to the remote (machine learning) machines. You'll need ansible installed locally (not on the machine learning boxes).
|
||||
For macOS users, the easiest way to install Ansible is via [Homebrew](https://brew.sh/):
|
||||
|
||||
```bash
|
||||
$ brew install ansible
|
||||
```
|
||||
|
||||
If that's not your cup of tea, install Ansible by following the directions for your machine [here](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#installing-the-control-machine).
|
||||
|
||||
---
|
||||
|
||||
### Configuration
|
||||
|
||||
Gather the following:
|
||||
|
||||
- SSH key or user credentials for the remote account
|
||||
|
||||
**Note:** Ansible does not expose a channel to allow communication between the user and the ssh process to accept a password manually to decrypt an ssh key when using the ssh connection plugin (which is the default). The use of `ssh-agent` is highly recommended.
|
||||
|
||||
- List of servers you wish to manage:
|
||||
- hostnames/IP addresses
|
||||
- SSH port
|
||||
- usernames
|
||||
|
||||
Copy [hosts.example] to `/etc/ansible/hosts` (if it does not already exist). Populate the `hosts` file (no extension) with the information about the servers you gathered above.
|
||||
|
||||
Confirm that you have populated your Ansible hosts file correctly:
|
||||
|
||||
```bash
|
||||
$ ansible-inventory --list
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Running
|
||||
|
||||
Once you're satisfied that you correctly populated your `hosts` file, update the `- hosts:` line of [tensorflow.yml] to reflect the hosts or groups you want to configure.
|
||||
|
||||
Examples:
|
||||
|
||||
- Apply against a single host defined as `ml2` in `/etc/ansible/hosts`:
|
||||
```yaml
|
||||
- hosts: ml2
|
||||
```
|
||||
- Apply against a group of hosts defined as `production` in `/etc/ansible/hosts`:
|
||||
```yaml
|
||||
- hosts: production
|
||||
```
|
||||
- Apply against all hosts defined in `/etc/ansible/hosts`:
|
||||
```yaml
|
||||
- hosts: all
|
||||
```
|
||||
|
||||
Then, when you're ready, run the playbook:
|
||||
|
||||
```bash
|
||||
$ ansible-playbook packages.yml --ask-become-pass
|
||||
```
|
||||
|
||||
**Note:** You must have `sudo` access to run the playbook!
|
||||
|
||||
Review the output:
|
||||
|
||||
- `[ok]` means no change (this task was already completed)
|
||||
- `[changed]` means the task successfully ran and the change was applied
|
||||
- `[unreachable]` means the host could not be reached
|
||||
- `[failed]` means the task ran but failed to complete
|
||||
|
||||
`[ok]` and `[changed]` are successful outcomes. Any `[unreachable]` and `[failed]` outputs should be investigated and resolved.
|
||||
|
||||
**Note:** This Ansible playbook is idempotent; once a configuration has been successfully applied, if you apply it again, all actions will report `[ok]`.
|
||||
|
||||
## Executing Tensorflow Jobs in Your New Environment
|
||||
|
||||
1. Point your browser to http://<hostname>:8888 and login with the password you provided.
|
||||
2. The `jupyter.volumes.source` folder will be mounted as the `notebooks` folder.
|
||||
3. Edit and execute your Jupyter notebooks as normal!
|
||||
|
||||
### Command Line Access
|
||||
|
||||
If you need to drop into a GPU-powered TensorFlow environment, SSH into the remote machine and execute the following:
|
||||
|
||||
```bash
|
||||
$ docker run --runtime=nvidia -it --rm tensorflow/tensorflow:latest-gpu-py3 bash
|
||||
```
|
||||
|
||||
**Note:** You must be a member of the `docker` group or have `sudo` access on the _remote machine_ to execute docker commands.
|
||||
|
||||
---
|
||||
|
||||
## Additional Files
|
||||
|
||||
- [ansible.cfg](ansible.cfg) enables SSH credential forwarding. This is a necessary step during data synchronization, as Ansible delegates those credentials to the master/writer host to push the data folder out to each of the mirrors.
|
||||
- [Dockerfile](Dockerfile) is used to build the Arricor TensorFlow image. See [Docker.md](Docker.md) for additional details.
|
||||
- [hosts.example](hosts.example) is an example of the Ansible inventory hosts file saved in `/etc/ansible/hosts`
|
||||
- [secrets.example.yml](secrets.example.yml) is an example of the expected structure of the `secrets.yml` file
|
||||
@@ -1,93 +0,0 @@
|
||||
# Configuration Management Tool Selection
|
||||
|
||||
## Summary
|
||||
|
||||
Ansible is proposed as the configuration management tool for this project due to the following characteristics:
|
||||
|
||||
- no agent installation on the managed nodes
|
||||
- push-based configuration changes do not require a separate machine to be provisioned
|
||||
- commands can be pushed from any developer/operator workstation
|
||||
- all updates are performed over SSH
|
||||
|
||||
## Tools Considered
|
||||
|
||||
Where a tool offers an open source and an enterprise version (e.g., Puppet, Terraform), only the open source version was considered. Web or other graphical user interfaces (GUIs) were not considered, as the goal of this phase is to produce infrastructure as code which can be run (and re-run) from the command line interface (CLI).
|
||||
|
||||
- [Ansible](#Ansible)
|
||||
- [Chef](#Chef)
|
||||
- [Puppet](#Puppet)
|
||||
- [Salt](#Salt)
|
||||
- [Terraform](#Terraform)
|
||||
|
||||
### Ansible
|
||||
|
||||
[Ansible's simple interface and usability fit right into the sys admin mindset, and in a shop with lots of Linux and Unix systems, Ansible is quick and easy to run right out of the gate](https://www.infoworld.com/article/2609482/data-center/data-center-review-puppet-vs-chef-vs-ansible-vs-Salt.html?page=4).
|
||||
|
||||
#### Ansible Pros
|
||||
|
||||
- Requires no agent installation on the managed nodes.
|
||||
- Push-based.
|
||||
- Does not require a separate machine to be provisioned. Commands can be pushed from any developer/operator workstation.
|
||||
- All updates are performed over SSH.
|
||||
|
||||
#### Ansible Cons
|
||||
|
||||
- Push-based synchronization means that the configuration is only refreshed on demand.
|
||||
|
||||
### Chef
|
||||
|
||||
[Chef has a stable and well-designed layout, and while it's not quite up to the level of Puppet in terms of raw features, it's a very capable solution. Chef may pose the most difficult learning curve to administrators who lack significant programming experience, but it could be the most natural fit for development-minded admins and development shops](https://www.infoworld.com/article/2609482/data-center/data-center-review-puppet-vs-chef-vs-ansible-vs-Salt.html?page=4).
|
||||
|
||||
#### Chef Pros
|
||||
|
||||
- AWS OpsWorks is based on Chef; any future migration to AWS could benefit from the existing configuration files.
|
||||
|
||||
#### Chef Cons
|
||||
|
||||
- **(Fatal)** Requires a master server and a workstation that will need to be maintained separately from the already provisioned deep learning machines.
|
||||
- **(Fatal)** Requires an agent (client) to be installed on each machine.
|
||||
- Requires an on-premises Chef server and [Push Jobs](https://docs.chef.io/push_jobs.html) plugin to push configurations manually. Otherwise, managed machines must check in with the master on a schedule.
|
||||
|
||||
### Puppet
|
||||
|
||||
[Puppet is the most mature and probably the most approachable of the four from a usability standpoint, though a solid knowledge of Ruby is highly recommended. Puppet is not as streamlined as Ansible or Salt, and its configuration can get Byzantine at times. Puppet is the safest bet for heterogeneous environments, but you may find Ansible or Salt to be a better fit in a larger or more homogenous infrastructure](https://www.infoworld.com/article/2609482/data-center/data-center-review-puppet-vs-chef-vs-ansible-vs-salt.html?page=4).
|
||||
|
||||
#### Puppet Pros
|
||||
|
||||
- Configuration can be kept up to date via a schedule or manual configuration pushes.
|
||||
|
||||
#### Puppet Cons
|
||||
|
||||
- **(Fatal)** Requires a "puppet master" (server) that will need to be maintained separately from the already provisioned machines.
|
||||
- **(Fatal)** Requires an agent (client) to be installed on each machine.
|
||||
|
||||
### Salt
|
||||
|
||||
[Salt is the sleekest and most robust of the four, and like Ansible it will resonate with sys admins. Highly scalable and quite capable, Salt is hamstrung only by the Web UI](https://www.infoworld.com/article/2609482/data-center/data-center-review-puppet-vs-chef-vs-ansible-vs-salt.html?page=4).
|
||||
|
||||
#### Salt Pros
|
||||
|
||||
- Push-based.
|
||||
- Can function via regular SSH or via client agents called "minions".
|
||||
|
||||
#### Salt Cons
|
||||
|
||||
- When running agentless, push-based synchronization means that the configuration is only refreshed on demand.
|
||||
|
||||
### Terraform
|
||||
|
||||
The initial hope was that [Terraform](https://terraform.io) could be used for configuration management for this project. However, after reviewing the [available Terraform provider plugins](https://terraform.io/docs/providers) and other available material, it was agreed on 23 January 2019 that Terraform was not suitable for this stage of the project.
|
||||
|
||||
In the future, if Arricor migrates its instances to a cloud service provider (CSP) such as AWS, Azure, or Google Cloud Platform, this configuration may be reusable as a first step via the [terraform-provisioner-ansible](https://github.com/jonmorehouse/terraform-provisioner-ansible) plugin. This plugin allows the user to create CSP instances, then execute the given Ansible playbook against those instances.
|
||||
|
||||
#### Terraform Pros
|
||||
|
||||
- Cloud native with support for multiple service providers.
|
||||
|
||||
#### Terraform Cons
|
||||
|
||||
- **(Fatal)** No support for provisioning bare metal instances.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Ansible allows for management of a server from scratch, with only the requirement to have a valid username and password. Additionally, its agentless approach avoids having to configure and maintain an admin server, further simplifying operations at the scale Arricor requires.
|
||||
@@ -1,5 +0,0 @@
|
||||
[defaults]
|
||||
host_key_checking = False
|
||||
|
||||
[ssh_connection]
|
||||
ssh_args = -o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
all:
|
||||
vars:
|
||||
ansible_python_interpreter: /usr/bin/python3
|
||||
test:
|
||||
hosts:
|
||||
test1:
|
||||
ansible_host: 127.0.0.1 # Replace with your remote IP
|
||||
ansible_port: 2222 # Replace with your remote SSH port
|
||||
ansible_user: vagrant # Replace wtih your username
|
||||
|
||||
production:
|
||||
hosts:
|
||||
writer:
|
||||
ansible_host: 192.168.1.100 # Replace with your remote IP
|
||||
ansible_port: 2202 # Replace with your remote SSH port
|
||||
ansible_user: ansible # Replace wtih your username
|
||||
mirror1:
|
||||
ansible_host: 192.168.1.101 # Replace with your remote IP
|
||||
ansible_port: 2202 # Replace with your remote SSH port
|
||||
ansible_user: ansible # Replace wtih your username
|
||||
mirror2:
|
||||
ansible_host: 192.168.1.102 # Replace with your remote IP
|
||||
ansible_port: 2202 # Replace with your remote SSH port
|
||||
ansible_user: ansible # Replace wtih your username
|
||||
@@ -1,38 +0,0 @@
|
||||
################################################################################
|
||||
# This file consists of three main sections:
|
||||
# 1. vars - variables used throughout the playbook are defined here. If you want to change packages or version, this is the place to do it.
|
||||
# 2. tasks - these are the steps that will be executed by the playbook. This is a straightforward, sequential playbook.
|
||||
# 3. handlers - these steps run only in response to specific events. If the event does not occur, the handler does not run.
|
||||
################################################################################
|
||||
---
|
||||
- hosts: test # Alternatively, 'canary', 'blue'|'green', 'all' according to your deployment strategy and your /etc/ansible/hosts file
|
||||
become: yes # All commands must run as root
|
||||
strategy: free # Allows all hosts to run to the end of the playbook as fast as they can
|
||||
|
||||
vars_files:
|
||||
- secrets.yml
|
||||
|
||||
roles:
|
||||
- role: packages # General Dependencies
|
||||
tags: [packages]
|
||||
|
||||
# - role: rsync # Rsync Setup
|
||||
# tags: [rsync]
|
||||
# vars:
|
||||
# sync: "{{ secrets.sync }}"
|
||||
|
||||
- role: docker # General Docker setup
|
||||
tags: [docker]
|
||||
vars:
|
||||
users: "{{ secrets.users }}"
|
||||
|
||||
- role: cuda # CUDA Driver Setup
|
||||
tags: [cuda]
|
||||
|
||||
- role: nvidia # NVIDIA-Docker Runtime Setup
|
||||
tags: [nvidia]
|
||||
|
||||
- role: jupyter # Launch Jupyter Container in Docker
|
||||
tags: [jupyter]
|
||||
vars:
|
||||
volumes: "{{ secrets.volumes }}"
|
||||
@@ -1,23 +0,0 @@
|
||||
# The `cuda` Role
|
||||
|
||||
The `cuda` role installs the Nvidia CUDA GPU repository and drivers.
|
||||
|
||||
This role may be executed independently by running:
|
||||
|
||||
```bash
|
||||
$ ansible-playbook packages.yml --tags "cuda"
|
||||
```
|
||||
|
||||
On execution, this role installs the following directly to the remote machine's operating system:
|
||||
|
||||
### Apt Repositories (Debian/Ubuntu)
|
||||
|
||||
- Nvidia CUDA
|
||||
|
||||
### Apt GPG Signing Keys (Debian/Ubuntu)
|
||||
|
||||
- cudatools <cudatools@nvidia.com>
|
||||
|
||||
### Operating System Packages (Debian/Ubuntu)
|
||||
|
||||
- cuda v10.x
|
||||
Binary file not shown.
@@ -1,5 +0,0 @@
|
||||
---
|
||||
# CUDA Driver Setup
|
||||
- name: reboot the machine
|
||||
reboot:
|
||||
listen: "reboot the machine"
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
# Cuda Driver Package Installation
|
||||
- name: copy the CUDA repo onto the machine
|
||||
copy:
|
||||
src: "{{ cuda.apt.repo }}"
|
||||
dest: "{{ general.working_dir }}/{{ cuda.apt.repo }}"
|
||||
|
||||
- name: get the CUDA signing key
|
||||
apt_key:
|
||||
state: present
|
||||
url: "{{ cuda.apt.signing_key_url }}"
|
||||
|
||||
- name: add the CUDA repo
|
||||
apt:
|
||||
deb: "{{ general.working_dir }}/{{ cuda.apt.repo }}"
|
||||
state: present
|
||||
|
||||
- name: install the CUDA drivers
|
||||
apt:
|
||||
name: "{{ cuda.apt.package }}"
|
||||
update_cache: yes
|
||||
notify: "reboot the machine"
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
- import_tasks: debian.yml
|
||||
when: ansible_facts['os_family']|lower == 'debian' # debian, ubuntu
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
cuda:
|
||||
apt:
|
||||
package: cuda=10.* # known good with 10.0.130-1
|
||||
repo: cuda-repo-ubuntu1804_10.0.130-1_amd64.deb # Network install
|
||||
signing_key_url: https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
|
||||
|
||||
general:
|
||||
working_dir: /tmp
|
||||
@@ -1,33 +0,0 @@
|
||||
# The `docker` Role
|
||||
|
||||
The `docker` role installs the Docker CE repository and runtime packages.
|
||||
|
||||
This role may be executed independently by running:
|
||||
|
||||
```bash
|
||||
$ ansible-playbook packages.yml --tags "docker"
|
||||
```
|
||||
|
||||
On execution, this role installs the following directly to the remote machine's operating system:
|
||||
|
||||
### Apt Repositories (Debian/Ubuntu)
|
||||
|
||||
- Docker CE
|
||||
|
||||
### Apt GPG Signing Keys (Debian/Ubuntu)
|
||||
|
||||
- Docker Release (CE deb) <docker@docker.com>
|
||||
|
||||
### Operating System Packages (Debian/Ubuntu)
|
||||
|
||||
- docker-ce v5:18.x
|
||||
|
||||
### System Services
|
||||
|
||||
- `docker` (enabled and started)
|
||||
|
||||
### User Groups
|
||||
|
||||
- docker
|
||||
|
||||
All users listed under `secrets.users` in `secrets.yml` will be added to the `docker` group.
|
||||
@@ -1,17 +0,0 @@
|
||||
---
|
||||
# Docker Package Installation
|
||||
- name: add Docker's official GPG key
|
||||
apt_key:
|
||||
state: present
|
||||
url: "{{ docker.apt.signing_key_url }}"
|
||||
|
||||
- name: add Docker apt repository
|
||||
apt_repository:
|
||||
repo: "{{ docker.apt.repo }}"
|
||||
state: present
|
||||
|
||||
- name: install Docker CE
|
||||
apt:
|
||||
name: "{{ docker.apt.package }}"
|
||||
state: present
|
||||
update_cache: yes
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
# General Docker Setup
|
||||
- import_tasks: debian.yml
|
||||
when: ansible_facts['os_family']|lower == 'debian' # debian, ubuntu
|
||||
|
||||
- name: ensure the docker service starts at boot
|
||||
systemd:
|
||||
name: "{{ docker.service_name }}"
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: create Docker group to avoid running as root
|
||||
group:
|
||||
name: "{{ docker.group_name }}"
|
||||
state: present
|
||||
|
||||
- name: add users to Docker group
|
||||
user:
|
||||
append: yes
|
||||
groups:
|
||||
- "{{ docker.group_name }}"
|
||||
name: "{{ item }}"
|
||||
loop: "{{ users }}"
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
docker:
|
||||
apt:
|
||||
package: docker-ce=5:18.* # known good with 5:18.09.1~3-0~ubuntu-bionic
|
||||
repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable
|
||||
signing_key_url: https://download.docker.com/linux/ubuntu/gpg
|
||||
group_name: docker
|
||||
service_name: docker
|
||||
@@ -1,31 +0,0 @@
|
||||
# The `nvidia` Role
|
||||
|
||||
The `nvidia` role installs the Nvidia Docker runtime, enabling access to Nvidia CUDA GPU hardware from within Docker containers.
|
||||
|
||||
This role may be executed independently by running:
|
||||
|
||||
```bash
|
||||
$ ansible-playbook packages.yml --tags "nvidia"
|
||||
```
|
||||
|
||||
On execution, this role installs the following directly to the remote machine's operating system:
|
||||
|
||||
### Apt Repositories (Debian/Ubuntu)
|
||||
|
||||
- libnvidia_container
|
||||
- nvidia_container_runtime
|
||||
- nvidia_docker
|
||||
|
||||
### Apt GPG Signing Keys (Debian/Ubuntu)
|
||||
|
||||
- NVIDIA CORPORATION (Open Source Projects) <cudatools@nvidia.com>
|
||||
|
||||
### Operating System Packages (Debian/Ubuntu)
|
||||
|
||||
- nvidia-docker2 v2.x
|
||||
|
||||
Containers are launched with the Nvidia Docker runtime by passing the `--runtime=nvidia` flag, e.g.,
|
||||
|
||||
```bash
|
||||
$ docker run --rm --runtime=nvidia nvidia/cuda nvidia-smi
|
||||
```
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
- name: reload the docker service
|
||||
systemd:
|
||||
name: docker
|
||||
state: reloaded
|
||||
listen: "reload the docker service"
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
# Nvidia Docker Runtime Installation
|
||||
- name: get the NVIDIA signing key
|
||||
apt_key:
|
||||
state: present
|
||||
url: "{{ nvidia.apt.signing_key_url }}"
|
||||
|
||||
- name: add the libnvidia-container repo
|
||||
apt_repository:
|
||||
filename: "{{ nvidia.apt.repo_filename }}"
|
||||
repo: "{{ nvidia.apt.repos.libnvidia_container }}"
|
||||
state: present
|
||||
|
||||
- name: add the nvidia-container-runtime repo
|
||||
apt_repository:
|
||||
filename: "{{ nvidia.apt.repo_filename }}"
|
||||
repo: "{{ nvidia.apt.repos.nvidia_container_runtime }}"
|
||||
state: present
|
||||
|
||||
- name: add the nvidia-docker repo
|
||||
apt_repository:
|
||||
filename: "{{ nvidia.apt.repo_filename }}"
|
||||
repo: "{{ nvidia.apt.repos.nvidia_docker }}"
|
||||
state: present
|
||||
|
||||
- name: install the nvidia-docker2 runtime
|
||||
apt:
|
||||
name: "{{ nvidia.apt.package }}"
|
||||
state: present
|
||||
update_cache: yes
|
||||
notify: "reload the docker service"
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
# Nvidia Docker Runtime Setup
|
||||
- import_tasks: debian.yml
|
||||
when: ansible_facts['os_family']|lower == 'debian' # debian, ubuntu
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
nvidia:
|
||||
apt:
|
||||
package: nvidia-docker2=2.* # known good with 2.0.3+docker18.09.1-1
|
||||
repo_filename: nvidia_github_io_nvidia_docker_ubuntu18_04_nvidia_docker.list
|
||||
repos:
|
||||
libnvidia_container: deb https://nvidia.github.io/libnvidia-container/ubuntu18.04/$(ARCH) /
|
||||
nvidia_container_runtime: deb https://nvidia.github.io/nvidia-container-runtime/ubuntu18.04/$(ARCH) /
|
||||
nvidia_docker: deb https://nvidia.github.io/nvidia-docker/ubuntu18.04/$(ARCH) /
|
||||
signing_key_url: https://nvidia.github.io/nvidia-docker/gpgkey
|
||||
@@ -1,26 +0,0 @@
|
||||
# The `packages` Role
|
||||
|
||||
The `packages` role installs the operating system and Python pre-requisites that are required to execute the other roles.
|
||||
|
||||
This role may be executed independently by running:
|
||||
|
||||
```bash
|
||||
$ ansible-playbook packages.yml --tags "packages"
|
||||
```
|
||||
|
||||
On execution, this role installs the following directly to the remote machine's operating system:
|
||||
|
||||
### Operating System Packages (Debian/Ubuntu)
|
||||
|
||||
- apt-transport-https v1.x
|
||||
- ca-certificates v20180409
|
||||
- curl v7.x
|
||||
- gnupg-agent v2.x
|
||||
- python-apt v1.x
|
||||
- python-pip v9.x
|
||||
- python-setuptools v39.x
|
||||
- software-properties-common v0.96.24.32.7
|
||||
|
||||
### Python (pip) Packages
|
||||
|
||||
- docker v3.7.0 or greater
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
# General Dependencies
|
||||
- name: install general apt dependencies
|
||||
apt:
|
||||
name: "{{ general.dependencies.apt }}"
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: install general pip dependencies for Ansible
|
||||
pip:
|
||||
name: "{{ general.dependencies.pip }}"
|
||||
state: present
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
- import_tasks: debian.yml
|
||||
when: ansible_facts['os_family']|lower == 'debian' # debian, ubuntu
|
||||
@@ -1,17 +0,0 @@
|
||||
---
|
||||
# General Dependencies
|
||||
general:
|
||||
dependencies:
|
||||
apt:
|
||||
- apt-transport-https=1.* # known good with 1.6.6ubuntu0.1 all
|
||||
- ca-certificates=20180409 # known good with 20180409
|
||||
- curl=7.* # known good with 7.58.0-2ubuntu3.5
|
||||
- gnupg-agent=2.* # known good with 2.2.4-1ubuntu1.2
|
||||
- python3-apt=1.* # known good with 1.6.3
|
||||
- python3-pip=9.* # known good with 9.0.1-2.3~ubuntu1
|
||||
- python3-setuptools=39.* # known good with 39.0.1-2
|
||||
- software-properties-common=0.96.24.32.7 # known good with 0.96.24.32.7
|
||||
- git
|
||||
- golang
|
||||
pip:
|
||||
- docker>=3.7.0 # known good with 3.7.0
|
||||
@@ -1,16 +0,0 @@
|
||||
motd file = /etc/rsyncd.motd
|
||||
log file = /var/log/rsyncd.log
|
||||
pid file = /var/run/rsyncd.pid
|
||||
lock file = /var/run/rsync.lock
|
||||
|
||||
[jupyter_data]
|
||||
path = /nfs/jupyter/data
|
||||
comment = Jupyter data files
|
||||
uid = nobody
|
||||
gid = nobody
|
||||
read only = yes
|
||||
list = yes
|
||||
auth users = @rsync:ro
|
||||
secrets file = /etc/rsyncd.secrets
|
||||
hosts allow = 192.168.1.0/24
|
||||
hosts deny = 0.0.0.0/0
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
- name: restart the rsync service
|
||||
systemd:
|
||||
name: "{{ rsync.service_name }}"
|
||||
state: restarted
|
||||
@@ -1,26 +0,0 @@
|
||||
---
|
||||
# Configure the rsync daemon on the master
|
||||
- name: copy rsync.conf up to the server
|
||||
copy:
|
||||
src: "{{ rsync.config_file.src }}"
|
||||
dest: "{{ rsync.config_file.dest }}"
|
||||
notify:
|
||||
- restart the rsync service
|
||||
when: inventory_hostname == rsync.master
|
||||
|
||||
- name: configure rsync on the server
|
||||
service:
|
||||
enabled: yes
|
||||
name: "{{ rsync.service_name }}"
|
||||
state: started
|
||||
when: inventory_hostname == rsync.master
|
||||
|
||||
# Synchronize the data folder across hosts
|
||||
- name: synchronize the data folder
|
||||
delegate_to: "{{ rsync.master }}"
|
||||
synchronize:
|
||||
src: "{{ sync.source }}"
|
||||
dest: "{{ sync.destination }}"
|
||||
rsync_opts: "{{ rsync.options }}"
|
||||
use_ssh_args: yes
|
||||
when: inventory_hostname != rsync.master
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
rsync:
|
||||
config_file:
|
||||
src: rsyncd.conf
|
||||
dest: /etc/rsyncd.conf
|
||||
master: ml1
|
||||
options:
|
||||
- "-e ssh"
|
||||
- "--no-motd"
|
||||
service_name: rsync
|
||||
@@ -1,15 +0,0 @@
|
||||
################################################################################
|
||||
# This file contains secrets that should not be checked into VCS.
|
||||
################################################################################
|
||||
---
|
||||
secrets:
|
||||
# Cachux7I
|
||||
password_hash: sha1:b9bbcb5e92ad:0358d2ce7c34192afa50fc5e5143ed91d75eda0d
|
||||
sync:
|
||||
source: /nfs/data
|
||||
destination: /nfs
|
||||
users:
|
||||
- ansible
|
||||
volumes:
|
||||
data: /nfs/data:/data
|
||||
source: /nfs/src:/tf
|
||||
386
generate/generate.go
Normal file
386
generate/generate.go
Normal file
@@ -0,0 +1,386 @@
|
||||
// Package generate The purpose of this package is to ensure that we can extend the use-case of P2PRC.
|
||||
// We will create a project directory with the template to extend the use-case of P2PRC
|
||||
package generate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.sr.ht/~akilan1999/p2p-rendering-computation/config"
|
||||
"github.com/otiai10/copy"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
modfile "golang.org/x/mod/modfile"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// NewProject Struct information required when creating a new project
|
||||
type NewProject struct {
|
||||
Name string
|
||||
Module string
|
||||
NewDir string
|
||||
P2PRCPath string
|
||||
CurrentModule string
|
||||
Option *copy.Options
|
||||
Token *token.FileSet
|
||||
AST *ast.File
|
||||
FileNameAST string
|
||||
}
|
||||
|
||||
// GenerateNewProject creates a new copy of the P2PRC
|
||||
// project for custom modification
|
||||
func GenerateNewProject(name string, module string) error {
|
||||
// Create new variable of type NewProject
|
||||
var newProject NewProject
|
||||
//Setting module name to the new project
|
||||
newProject.Module = module
|
||||
// Get path of the current directory
|
||||
curDir, err := config.GetCurrentPath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Folder name of the new generated project
|
||||
newProject.NewDir = curDir + name + "/"
|
||||
// Create a new folder based on name entered
|
||||
err = CreateFolder(name, curDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// get path of P2PRC
|
||||
P2PRCPATH, err := config.GetPathP2PRC()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Assign P2PRC path to the newly generated project
|
||||
newProject.P2PRCPath = P2PRCPATH
|
||||
// Steps:
|
||||
// - copy all files from P2PRC
|
||||
// - remove go.mod and go.sum and create new ones
|
||||
|
||||
// Files we require to skip
|
||||
|
||||
var Options copy.Options
|
||||
|
||||
// IF YOU ARE RELEASING AN EXTENSION OF P2PRC
|
||||
// MODIFY HERE (AN EXTENSION FROM YOUR EXTENSION :P)
|
||||
// Skip or have the appropriate files and directories not needed
|
||||
//----------------------------------------------------------------
|
||||
// Action performed:
|
||||
// - Ensuring main.go file exists
|
||||
// - Ensuring generate.go file exists
|
||||
// - Ensuring modifyGenerate.go file exists
|
||||
// - Ensuring generate_test.go file exists
|
||||
// - Ensuring server/server.go file exists
|
||||
// - Ensuring server/gopsutil.go file exists
|
||||
// - Ensuring server/gpu.go file exists
|
||||
// - Ensuring cmd/action.go file exists
|
||||
// - Ensuring cmd/flags.go file exists
|
||||
// - Skipping all .go files apart from the ones listed above
|
||||
// - Skipping go.mod file
|
||||
// - Skipping go.sum file
|
||||
// - Skipping .idea/ directory
|
||||
// - Skipping Makefile file
|
||||
// - Skipping <Project Name>/ directory
|
||||
//----------------------------------------------------------------
|
||||
Options.Skip = func(src string) (bool, error) {
|
||||
switch {
|
||||
case strings.HasSuffix(src, "main.go"):
|
||||
return false, nil
|
||||
case strings.HasSuffix(src, "generate.go"):
|
||||
return false, nil
|
||||
case strings.HasSuffix(src, "modifyGenerate.go"):
|
||||
return false, nil
|
||||
case strings.HasSuffix(src, "generate_test.go"):
|
||||
return false, nil
|
||||
case strings.HasSuffix(src, "server/server.go"):
|
||||
return false, nil
|
||||
case strings.HasSuffix(src, "server/gopsutil.go"):
|
||||
return false, nil
|
||||
case strings.HasSuffix(src, "server/gpu.go"):
|
||||
return false, nil
|
||||
case strings.HasSuffix(src, "cmd/action.go"):
|
||||
return false, nil
|
||||
case strings.HasSuffix(src, "cmd/flags.go"):
|
||||
return false, nil
|
||||
case strings.HasSuffix(src, "config/config.go"):
|
||||
return false, nil
|
||||
case strings.HasSuffix(src, "config/config_test.go"):
|
||||
return false, nil
|
||||
case strings.HasSuffix(src, ".go"):
|
||||
return true, nil
|
||||
case strings.HasSuffix(src, "go.mod"):
|
||||
return true, nil
|
||||
case strings.HasSuffix(src, "go.sum"):
|
||||
return true, nil
|
||||
case strings.HasSuffix(src, ".idea"):
|
||||
return true, nil
|
||||
case strings.HasSuffix(src, "Makefile"):
|
||||
return true, nil
|
||||
case strings.HasSuffix(src, name):
|
||||
return true, nil
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Storing type option in the struct new project
|
||||
newProject.Option = &Options
|
||||
|
||||
// Copies all files from P2PRC to the new project created
|
||||
err = copy.Copy(newProject.P2PRCPath, newProject.NewDir, *newProject.Option)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Creating a new go.mod file in the appropriate directory
|
||||
err = newProject.CreateGoMod()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get current project mod name
|
||||
err = newProject.GetCurrentGoModule()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Change the appropriate imports
|
||||
err = newProject.ChangeImportFiles()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add changes inside the new project
|
||||
err = newProject.GitAdd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// commit changes inside the new project
|
||||
err = newProject.GitCommit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Creates go.sum file
|
||||
//err = newProject.CreateGoModTidy()
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateFolder Creates a new folder based on the name and path provided
|
||||
func CreateFolder(name string, path string) error {
|
||||
//Create a folder/directory at a full qualified path
|
||||
err := os.Mkdir(path+name, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateGoMod Creates a new go module for the new project created
|
||||
func (a *NewProject) CreateGoMod() error {
|
||||
// Create new go.mod in the appropriate directory
|
||||
cmd := exec.Command("go", "mod", "init", a.Module)
|
||||
cmd.Dir = a.NewDir
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *NewProject) CreateGoModTidy() error {
|
||||
// Installs all the appropriate dependencies and creates go.sum
|
||||
cmd := exec.Command("go", "mod", "tidy")
|
||||
cmd.Dir = a.NewDir
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChangeImportFiles Changes Appropriate imports in the appropriate file
|
||||
func (a *NewProject) ChangeImportFiles() error {
|
||||
// IF YOU ARE RELEASING AN EXTENSION OF P2PRC
|
||||
// MODIFY HERE (AN EXTENSION FROM YOUR EXTENSION :P)
|
||||
//----------------------------------------------------------------
|
||||
// Action performed:
|
||||
// Files we would need to modify the imports in
|
||||
// - generate/generate.go -> config module
|
||||
// - generate/generate_test.go -> config module
|
||||
// - cmd/action.go -> config module, server module, generate module
|
||||
// - cmd/flags.go -> config module, server module, generate module
|
||||
// - server/server.go -> config module
|
||||
// - main.go -> cmd module
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// 1.0 - generate/generate.go -> config module
|
||||
a.FileNameAST = a.NewDir + "generate/generate.go"
|
||||
// Get AST information of the file
|
||||
err := a.GetASTGoFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Change the appropriate Go file
|
||||
err = a.ChangeImports(a.CurrentModule+"/config", a.Module+"/config")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Writes the change to the appropriate file
|
||||
err = a.WriteGoAst()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
// 1.1 - generate/generate_test.go -> config module
|
||||
a.FileNameAST = a.NewDir + "generate/generate_test.go"
|
||||
// Get AST information of the file
|
||||
err = a.GetASTGoFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Change the appropriate Go file
|
||||
err = a.ChangeImports(a.CurrentModule+"/config", a.Module+"/config")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Writes the change to the appropriate file
|
||||
err = a.WriteGoAst()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
// 2.0 - cmd/action.go -> config module, server module, generate module
|
||||
a.FileNameAST = a.NewDir + "cmd/action.go"
|
||||
// Get AST information of the file
|
||||
err = a.GetASTGoFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Change the appropriate Go file
|
||||
err = a.ChangeImports(a.CurrentModule+"/config", a.Module+"/config")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = a.ChangeImports(a.CurrentModule+"/server", a.Module+"/server")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = a.ChangeImports(a.CurrentModule+"/generate", a.Module+"/generate")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Writes the change to the appropriate file
|
||||
err = a.WriteGoAst()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
// 2.1 - cmd/flags.go -> config module, server module, generate module
|
||||
a.FileNameAST = a.NewDir + "cmd/flags.go"
|
||||
// Get AST information of the file
|
||||
err = a.GetASTGoFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Change the appropriate Go file
|
||||
err = a.ChangeImports(a.CurrentModule+"/config", a.Module+"/config")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = a.ChangeImports(a.CurrentModule+"/server", a.Module+"/server")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = a.ChangeImports(a.CurrentModule+"/generate", a.Module+"/generate")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Writes the change to the appropriate file
|
||||
err = a.WriteGoAst()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
// 3.0 - server/server.go -> config module
|
||||
a.FileNameAST = a.NewDir + "server/server.go"
|
||||
// Get AST information of the file
|
||||
err = a.GetASTGoFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Change the appropriate Go file
|
||||
err = a.ChangeImports(a.CurrentModule+"/config", a.Module+"/config")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Writes the change to the appropriate file
|
||||
err = a.WriteGoAst()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
// 4.0 - server/server.go -> config module
|
||||
a.FileNameAST = a.NewDir + "main.go"
|
||||
// Get AST information of the file
|
||||
err = a.GetASTGoFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Change the appropriate Go file
|
||||
err = a.ChangeImports(a.CurrentModule+"/cmd", a.Module+"/cmd")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Writes the change to the appropriate file
|
||||
err = a.WriteGoAst()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetCurrentGoModule Gets the current go module name
|
||||
func (a *NewProject) GetCurrentGoModule() error {
|
||||
goModBytes, err := ioutil.ReadFile(a.P2PRCPath + "go.mod")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
modName := modfile.ModulePath(goModBytes)
|
||||
fmt.Fprintf(os.Stdout, "modName=%+v\n", modName)
|
||||
|
||||
// Set current module to struct of file NewProject
|
||||
a.CurrentModule = modName
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *NewProject) GitAdd() error {
|
||||
// Installs all the appropriate dependencies and creates go.sum
|
||||
cmd := exec.Command("git", "add", ".")
|
||||
cmd.Dir = a.NewDir
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *NewProject) GitCommit() error {
|
||||
// Installs all the appropriate dependencies and creates go.sum
|
||||
cmd := exec.Command("git", "commit", "-m=removed appropriate go files")
|
||||
cmd.Dir = a.NewDir
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
112
generate/generate_test.go
Normal file
112
generate/generate_test.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package generate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.sr.ht/~akilan1999/p2p-rendering-computation/config"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Tests the create folder function creates a folder
|
||||
// This test will create a folder in the temporary
|
||||
// directory
|
||||
func TestCreateFolder(t *testing.T) {
|
||||
err := CreateFolder("test", "/tmp/")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Testing if a new project is created successfully
|
||||
func TestGenerateNewProject(t *testing.T) {
|
||||
// Checking if a new project is created successfully
|
||||
err := GenerateNewProject("p2prctest","p2prctest")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Testing AST function to ensure imports are
|
||||
// working as intended
|
||||
func TestChangingImportAST(t *testing.T) {
|
||||
// Create a new variable of type NewProject
|
||||
var np NewProject
|
||||
// Get current directory
|
||||
path, err := config.GetCurrentPath()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
// Create testcase scenario
|
||||
err = config.Copy(path + "testcaseAST.go", path + "/Test/testcaseAST.go")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
// Sets new directory to the folder test
|
||||
np.NewDir = path + "Test/"
|
||||
// Sets file name to be opened and modified in the AST
|
||||
np.FileNameAST = path + "Test/" + "testcaseAST.go"
|
||||
// Call the Read AST function
|
||||
err = np.GetASTGoFile()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
// Change an import
|
||||
err = np.ChangeImports("fmt", "lolol")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
// Write those saved changes
|
||||
err = np.WriteGoAst()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Testing the if Go Mod is created
|
||||
func TestNewProject_CreateGoMod(t *testing.T) {
|
||||
// Create a new variable of type NewProject
|
||||
var np NewProject
|
||||
path, err := config.GetCurrentPath()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
// Set new project name as Test
|
||||
np.Name = "Test"
|
||||
// Set new project module as github.com/Test
|
||||
np.Module = "github.com/Test"
|
||||
// Set Path of the new project
|
||||
np.NewDir = path + "Test/"
|
||||
// Creating a go.mod file
|
||||
err = np.CreateGoMod()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Testing if the current go module is returned
|
||||
func TestNewProject_GetCurrentGoModule(t *testing.T) {
|
||||
// Create a new variable of type NewProject
|
||||
var np NewProject
|
||||
path, err := config.GetPathP2PRC()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
// Set Current project path
|
||||
np.P2PRCPath = path
|
||||
// Get module name
|
||||
err = np.GetCurrentGoModule()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Error(err)
|
||||
}
|
||||
fmt.Println(np.CurrentModule)
|
||||
}
|
||||
49
generate/modifyGenerate.go
Normal file
49
generate/modifyGenerate.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package generate
|
||||
|
||||
import (
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"os"
|
||||
)
|
||||
|
||||
|
||||
// GetASTGoFile Gets AST of the Go file provided
|
||||
func (np *NewProject)GetASTGoFile() error{
|
||||
fset := token.NewFileSet()
|
||||
node, err := parser.ParseFile(fset, np.FileNameAST, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Write Token information to the struct
|
||||
np.Token = fset
|
||||
// Write AST information the struct
|
||||
np.AST = node
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChangeImports Changes import of the AST
|
||||
func (np *NewProject)ChangeImports(CurrentImport string,ChangedImport string) error {
|
||||
// Iterating through the loop and changing the appropriate import
|
||||
for i, spec := range np.AST.Imports {
|
||||
// If the current import is found then change it
|
||||
if spec.Path.Value == "\"" + CurrentImport + "\"" {
|
||||
np.AST.Imports[i].Path.Value = "\"" + ChangedImport + "\""
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteGoAst Write changed imports back to the AST
|
||||
func (np *NewProject)WriteGoAst() error {
|
||||
// write new AST to file
|
||||
f, err := os.Create(np.FileNameAST)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer f.Close()
|
||||
if err := printer.Fprint(f, np.Token, np.AST); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
9
generate/testcaseAST.go
Normal file
9
generate/testcaseAST.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package generate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func TestCaseAST() {
|
||||
fmt.Println("lol")
|
||||
}
|
||||
9
go.mod
9
go.mod
@@ -5,10 +5,12 @@ go 1.15
|
||||
require (
|
||||
github.com/Microsoft/hcsshim v0.8.15 // indirect
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
||||
github.com/apenella/go-ansible v1.1.0
|
||||
github.com/containerd/continuity v0.0.0-20210315143101-93e15499afd5 // indirect
|
||||
github.com/docker/docker v20.10.0-beta1.0.20201113105859-b6bfff2a628f+incompatible
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/gin-gonic/gin v1.6.3
|
||||
github.com/go-git/go-git/v5 v5.4.2
|
||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||
github.com/google/go-cmp v0.5.4 // indirect
|
||||
github.com/google/uuid v1.1.2
|
||||
@@ -17,18 +19,17 @@ require (
|
||||
github.com/moby/sys/mount v0.2.0 // indirect
|
||||
github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/otiai10/copy v1.6.0
|
||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
|
||||
github.com/shirou/gopsutil v3.20.12+incompatible
|
||||
github.com/showwin/speedtest-go v1.1.1
|
||||
github.com/spf13/viper v1.4.0
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 // indirect
|
||||
gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 // indirect
|
||||
golang.org/x/mod v0.3.0
|
||||
golang.org/x/text v0.3.5 // indirect
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
|
||||
google.golang.org/grpc v1.35.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gotest.tools/v3 v3.0.3 // indirect
|
||||
)
|
||||
|
||||
89
go.sum
89
go.sum
@@ -55,18 +55,31 @@ github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn
|
||||
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
|
||||
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20201120081800-1786d5ef83d4/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/apenella/go-ansible v1.1.0 h1:wWqaZBvoDxPjvtwXc2fXbDj546uBj/Kv2PL7PW82EfY=
|
||||
github.com/apenella/go-ansible v1.1.0/go.mod h1:tHqFBSwWXF9k2hkLQWfq6oxMQZHslySQqttkA2siyqE=
|
||||
github.com/apenella/go-common-utils v0.1.1 h1:dJA2tY22z6mYB5a+EogfiS7NxZsR/Ld3TWnZcS3JPa0=
|
||||
github.com/apenella/go-common-utils v0.1.1/go.mod h1:E7RUbl9B1vdLkTIapoTE2W6pIgW7dTSJOxL3pf4gV6g=
|
||||
github.com/apenella/go-common-utils/error v0.0.0-20200917063805-34b0ed3c4ce1 h1:lw/fwF65AaJVxyUTJShtBiZfaiafKde3QkR4im1glzQ=
|
||||
github.com/apenella/go-common-utils/error v0.0.0-20200917063805-34b0ed3c4ce1/go.mod h1:Hj3S/BcSHKfv9VDMcrY7lsm9hGnb7cd70alSkl/Sv+4=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
||||
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
@@ -164,6 +177,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||
@@ -201,6 +215,8 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
|
||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
@@ -208,6 +224,9 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
@@ -220,6 +239,17 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||
github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34=
|
||||
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
|
||||
github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4=
|
||||
github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@@ -342,8 +372,13 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
@@ -356,6 +391,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
@@ -366,12 +403,14 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5nwm/V115vj2YXfhS0w=
|
||||
@@ -382,7 +421,10 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
|
||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
@@ -391,6 +433,7 @@ github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vq
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
@@ -417,6 +460,7 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
@@ -452,6 +496,14 @@ github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.m
|
||||
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
||||
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
||||
github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ=
|
||||
github.com/otiai10/copy v1.6.0/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E=
|
||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
|
||||
github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI=
|
||||
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
|
||||
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
|
||||
github.com/otiai10/mint v1.3.2 h1:VYWnrP5fXmz1MXvjuUvcBrXSjGE6xjON+axB/UrpO3E=
|
||||
github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
|
||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
@@ -500,10 +552,10 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shirou/gopsutil v3.20.12+incompatible h1:6VEGkOXP/eP4o2Ilk8cSsX0PhOEfX6leqAnD+urrp9M=
|
||||
github.com/shirou/gopsutil v3.20.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/showwin/speedtest-go v1.1.1 h1:anVwVssgk9MsN/ev8hXBcfMHAfu7o+6fUPvOYTQYkq8=
|
||||
github.com/showwin/speedtest-go v1.1.1/go.mod h1:Evr4so/j097J4zgdEyYvaBhzyKMgrTNUOwFQcXqUUzc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
@@ -545,8 +597,9 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
@@ -571,6 +624,8 @@ github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmF
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
|
||||
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
|
||||
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
|
||||
@@ -601,6 +656,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
@@ -608,8 +664,10 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -639,6 +697,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -672,8 +731,9 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897 h1:KrsHThm5nFk34YtATK1LsThyGhGbGe1olrte/HInHvs=
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -744,8 +804,11 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 h1:EZ2mChiOa8udjfp6rRmswTbtZN/QzUQp4ptM4rnjHvc=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79 h1:RX8C8PRZc2hTIod4ds8ij+/4RQX3AqhYj3uOHmyaz4E=
|
||||
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -875,8 +938,10 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
@@ -887,6 +952,8 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
||||
36
index.html
36
index.html
@@ -6,25 +6,37 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<img src="Docs/images/p2prclogo.png" alt="P2PRC">
|
||||
<img src="Docs/images/p2prclogo.png" alt="P2PRC Logo">
|
||||
<h1>P2PRC</h1>
|
||||
<b>A peer to peer network designed for computation</b>
|
||||
|
||||
<p>P2PRC is peer to peer to network designed for computation reasons.</p>
|
||||
<p>This project was developed during my 4th year dissertation at Heriot-Watt university and We are getting the
|
||||
project to a usable state. </p>
|
||||
<p> It's purpose is for people to use each others computers rather than servers such as AWS and Azure. </p>
|
||||
<p><dfn>P2PRC</dfn> is peer to peer to network designed for computation reasons.</p>
|
||||
<p>This project was developed during my 4th year dissertation at Heriot-Watt University and We are getting the
|
||||
project to a usable state.</p>
|
||||
<p> It's purpose is for people to use each others computers rather than servers such as <abbr title="Amazon Web Services">AWS</abbr> and <span title="Microsoft Azure">Azure</span>.</p>
|
||||
|
||||
<p><b>Project:</b></p>
|
||||
<ul>
|
||||
<li><a href="https://github.com/Akilan1999/p2p-rendering-computation">P2PRC on GitHub</a></li>
|
||||
<li><a href="https://discord.gg/b4nRGTjYqy">P2PRC Discord Server</a> <font color="red">(join here to chat!)</font></li>
|
||||
<li>
|
||||
<a href="https://github.com/Akilan1999/p2p-rendering-computation" target="_blank">P2PRC on GitHub</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://discord.gg/b4nRGTjYqy" target="_blank">P2PRC Discord Server</a> <span style="color: red;">(join here to chat!)</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p><b>Community Server to download public network</b></p>
|
||||
<ul>
|
||||
<li>
|
||||
<b>IP Address: 172.104.44.195</a></b>
|
||||
<b>Only for v1.0.0</b>
|
||||
<br>
|
||||
<!-- <b>IP Address: 172.104.44.195</b>-->
|
||||
<p>Use this server to only download part of the p2p network</p>
|
||||
</li>
|
||||
<li>
|
||||
<b>Master branch</b>
|
||||
<br>
|
||||
<!-- <b>IP Address: 139.162.246.221</b>-->
|
||||
<p>Use this server to only download part of the p2p network</p>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -33,15 +45,17 @@
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<b><a href="https://akilan.io">Akilan Selvacoumar</a></b>
|
||||
<b><a href="https://akilan.io" target="_blank"><span title="The Not So Boring Developer">Akilan Selvacoumar</span></a></b>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p><b>Other links:</b></p>
|
||||
<ul>
|
||||
<li><a href="https://www.youtube.com/channel/UChy18QB1hBzZ7MniIW_FJvQ">Akilan Selvacoumar on YouTube</a></li>
|
||||
<li><a href="https://www.youtube.com/channel/UChy18QB1hBzZ7MniIW_FJvQ" target="_blank">Akilan Selvacoumar on YouTube</a></li>
|
||||
<li><a href="https://akilan.io/projects/p2prc/" target="_blank">Project info from akilan.io</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</body></html>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
6
install.bat
Normal file
6
install.bat
Normal file
@@ -0,0 +1,6 @@
|
||||
go build -o p2prc.exe
|
||||
|
||||
setx PATH "%PATH%;%cd%"
|
||||
setx P2PRC "%cd%"
|
||||
|
||||
p2prc --dc
|
||||
11
install.sh
Normal file
11
install.sh
Normal file
@@ -0,0 +1,11 @@
|
||||
# This script setups up the project P2PRC
|
||||
# Call: sh install.sh <name of binary>
|
||||
echo '# Add the following paths to .bashrc or .zshrc based on the configuration you have set'
|
||||
echo export P2PRC=$PWD
|
||||
echo export PATH=$PWD:\${PATH}
|
||||
export P2PRC=${PWD}
|
||||
export PATH=${PWD}:${PATH}
|
||||
|
||||
# Expects an argument of the name of the binary
|
||||
go build -o ${1}
|
||||
./p2prc --dc
|
||||
2
main.go
2
main.go
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
// VERSION specifies the version of the platform
|
||||
var VERSION = "1.0.0"
|
||||
var VERSION = "1.5.0"
|
||||
var mode string
|
||||
|
||||
// Varaibles if mode is client
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"ip_address": [
|
||||
{
|
||||
"ipv4": "172.104.44.195",
|
||||
"ipv4": "139.162.246.221",
|
||||
"ipv6": "",
|
||||
"latency": 0,
|
||||
"download": 0,
|
||||
"upload": 0
|
||||
"upload": 0,
|
||||
"serverport": "8088"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -23,6 +23,7 @@ type IpAddress struct {
|
||||
Latency time.Duration `json:"latency"`
|
||||
Download float64 `json:"download"`
|
||||
Upload float64 `json:"upload"`
|
||||
ServerPort string `json:"serverport"`
|
||||
}
|
||||
|
||||
type IP struct {
|
||||
@@ -69,6 +70,7 @@ func ReadIpTable()(*IpAddresses ,error){
|
||||
}
|
||||
PublicIP.Ipv4 = ip
|
||||
PublicIP.Ipv6 = ipv6
|
||||
PublicIP.ServerPort = config.ServerPort
|
||||
|
||||
// Updates current machine IP address to the IP table
|
||||
ipAddresses.IpAddress = append(ipAddresses.IpAddress, PublicIP)
|
||||
@@ -116,10 +118,11 @@ func PrintIpTable() error {
|
||||
}
|
||||
|
||||
for i := 0; i < len(table.IpAddress); i++ {
|
||||
fmt.Printf("\nIP Address: %s\nIPV6: %s\nLatency: %s\n-----------" +
|
||||
fmt.Printf("\nIP Address: %s\nIPV6: %s\nLatency: %s\nServerPort: %s\n-----------" +
|
||||
"-----------------\n",table.IpAddress[i].Ipv4,table.IpAddress[i].Ipv6,
|
||||
table.IpAddress[i].Latency)
|
||||
table.IpAddress[i].Latency, table.IpAddress[i].ServerPort)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ func (s *IpAddress)UploadSpeed() error {
|
||||
|
||||
b, w := createMultipartFormData("file",config.SpeedTestFile)
|
||||
|
||||
req, err := http.NewRequest("GET", "http://" + s.Ipv4 + ":8088/upload", &b)
|
||||
req, err := http.NewRequest("GET", "http://" + s.Ipv4 + ":" + s.ServerPort + "/upload", &b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -152,10 +152,10 @@ func (s *IpAddress) PingTest() error {
|
||||
//pingURL := strings.Split(s.URL, "/upload")[0] + "/latency.txt"
|
||||
var pingURL string
|
||||
if s.Ipv6 != "" {
|
||||
pingURL = "http://[" + s.Ipv6 + "]:8088/server_info"
|
||||
pingURL = "http://[" + s.Ipv6 + "]:" + s.ServerPort + "/server_info"
|
||||
s.Ipv4 = ""
|
||||
} else {
|
||||
pingURL = "http://" + s.Ipv4 + ":8088/server_info"
|
||||
pingURL = "http://" + s.Ipv4 + ":" + s.ServerPort + "/server_info"
|
||||
}
|
||||
|
||||
l := time.Duration(100000000000) // 10sec
|
||||
|
||||
3
plugin/.dockerignore
Normal file
3
plugin/.dockerignore
Normal file
@@ -0,0 +1,3 @@
|
||||
.idea
|
||||
.DS_Store
|
||||
Dockerfile
|
||||
2
plugin/.gitignore
vendored
Normal file
2
plugin/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.idea
|
||||
.DS_Store
|
||||
102
plugin/README.md
Normal file
102
plugin/README.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Laplace
|
||||
|
||||
Laplace is an open-source project to enable screen sharing directly via browser.
|
||||
Made possible using WebRTC for low latency peer-to-peer connections, and WebSocket implemented in golang for WebRTC signaling.
|
||||
|
||||
> Demo video: https://youtu.be/E8cUaPrAlzE
|
||||
|
||||
[](https://youtu.be/E8cUaPrAlzE)
|
||||
|
||||
|
||||
## Try Demo
|
||||
|
||||
For demo, you can visit https://laplace.madeby.monster/
|
||||
|
||||

|
||||
|
||||
|
||||
## Motivation
|
||||
|
||||
There are already possible solutions to share your computer screen, e.g. TeamViewer.
|
||||
But most of them require installations of software or plugins.
|
||||
What Laplace provides is a simple solution to this problem.
|
||||
For users wanting to share their screen, all they need to do is to open a website page with their browsers, clicking some buttons, then share some session ID with their peers.
|
||||
No installation or registration required.
|
||||
|
||||
#### Solving the latency problem
|
||||
|
||||
This project also serves as a proof-of-concept (PoC) for screen sharing capability directly in browsers based on WebRTC.
|
||||
Using WebRTC, real-time communication is made possible through peer-to-peer connections.
|
||||
This proves to be very useful in solving one of the biggest problems is screen streaming: **Latency**.
|
||||
The latency represents how long the delay is from the source to transmit to the remote client.
|
||||
If you notice, this latency problem is usually highlighted by game streaming services, since gameplay relies heavily on the interactivity of inputs and outputs.
|
||||
|
||||
|
||||
#### Low server cost
|
||||
This solution also solves the server cost problem, since the expensive operations (encoding and transmission) are done on client browsers.
|
||||
The server is only needed for serving frontends and for WebRTC signaling.
|
||||
|
||||
|
||||
#### Possible Use Cases
|
||||
|
||||
- Game streaming from PC to mobile devices.
|
||||
- Collaborative work where you need to share your screen with remote coworkers.
|
||||
- Mirroring presentation slides and demonstrations.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Build from source
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/adamyordan/laplace.git
|
||||
$ cd laplace && go build -o laplace main.go
|
||||
$ ./laplace --help
|
||||
```
|
||||
|
||||
OR, pull the pre-built docker image
|
||||
|
||||
```bash
|
||||
$ docker pull adamyordan/laplace
|
||||
$ docker run adamyordan/laplace ./laplace --help
|
||||
```
|
||||
|
||||
|
||||
## Program Execution
|
||||
|
||||
Executing this project basically serves an HTTP server that will host the frontend and the WebSocket implementation.
|
||||
Note that you sometimes need to run HTTPs in order for browser to connect to websocket.
|
||||
|
||||
```bash
|
||||
$ ./laplace --help
|
||||
-addr string
|
||||
Listen address (default "0.0.0.0:443")
|
||||
-certFile string
|
||||
TLS cert file (default "files/server.crt")
|
||||
-keyFile string
|
||||
TLS key file (default "files/server.key")
|
||||
-tls
|
||||
Use TLS (default true)
|
||||
```
|
||||
|
||||
By default, you can run the executable without any argument to listen to TLS port 443.
|
||||
A self-signed certificate files are provided to ease up development.
|
||||
|
||||
```bash
|
||||
$ ./laplace
|
||||
2020/03/25 01:01:10 Listening on TLS: 0.0.0.0:443
|
||||
```
|
||||
|
||||
You can then open https://localhost:443/ to view Laplace page.
|
||||
You may need to add certificate exceptions. In Chrome, you can type `thisisunsafe`.
|
||||
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://choosealicense.com/licenses/mit/)
|
||||
1
plugin/TestAnsible/description.txt
Normal file
1
plugin/TestAnsible/description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Test if it's detected
|
||||
@@ -2,9 +2,9 @@
|
||||
all:
|
||||
vars:
|
||||
ansible_python_interpreter: /usr/bin/python3
|
||||
test:
|
||||
main:
|
||||
hosts:
|
||||
test1:
|
||||
host1:
|
||||
ansible_host: 0.0.0.0 # Replace with your remote IP
|
||||
ansible_port: 44003 # Replace with your remote SSH port
|
||||
ansible_user: master # Replace wtih your username
|
||||
8
plugin/TestAnsible/site.yml
Normal file
8
plugin/TestAnsible/site.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
|
||||
- hosts: all
|
||||
|
||||
tasks:
|
||||
- name: simple-ansibleplaybook
|
||||
debug:
|
||||
msg: Your are running 'simple-ansibleplaybook' example
|
||||
1
plugin/generate_test_case.sh
Normal file
1
plugin/generate_test_case.sh
Normal file
@@ -0,0 +1 @@
|
||||
cp -r plugin/TestAnsible/ plugin/deploy/
|
||||
65
plugin/packageManager.go
Normal file
65
plugin/packageManager.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"git.sr.ht/~akilan1999/p2p-rendering-computation/config"
|
||||
"github.com/go-git/go-git/v5"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// DownloadPlugin This functions downloads package from
|
||||
// a git repo.
|
||||
func DownloadPlugin(pluginurl string) error {
|
||||
// paring plugin url
|
||||
u, err := url.Parse(pluginurl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
path := u.Path
|
||||
// Trim first character of the string
|
||||
path = path[1:]
|
||||
// trim last element of the string
|
||||
path = path[:len(path)-1]
|
||||
// Replaces / with _
|
||||
folder := strings.Replace(path, "/", "_", -1)
|
||||
// Reads plugin path from the config path
|
||||
config, err := config.ConfigInit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// clones a repo and stores it at the plugin directory
|
||||
_, err = git.PlainClone(config.PluginPath + "/" + folder, false, &git.CloneOptions{
|
||||
URL: pluginurl,
|
||||
Progress: os.Stdout,
|
||||
})
|
||||
// returns error if raised
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeletePlugin The following function deletes a plugin based on
|
||||
// the plugin name provided.
|
||||
func DeletePlugin(pluginname string) error {
|
||||
config, err := config.ConfigInit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
plugin, err := SearchPlugin(pluginname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete the directory holding the plugin
|
||||
err = os.RemoveAll(config.PluginPath + "/" + plugin.FolderName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
452
plugin/plugin.go
Normal file
452
plugin/plugin.go
Normal file
@@ -0,0 +1,452 @@
|
||||
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"
|
||||
|
||||
"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
|
||||
}
|
||||
|
||||
// Plugin Information about the plugins available
|
||||
type Plugin struct {
|
||||
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
|
||||
}
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
var plugins *Plugins = new(Plugins)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// RunAnsible Executes based on credentials on the struct
|
||||
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"},
|
||||
}
|
||||
|
||||
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"),
|
||||
),
|
||||
),
|
||||
}
|
||||
|
||||
err := playbook.Run(context.TODO())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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")
|
||||
if err != nil {
|
||||
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"
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
c := &Host{}
|
||||
err = yaml.Unmarshal(buf, c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("in file %q: %v", filename, err)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
// we unmarshal our byteArray which contains our
|
||||
// jsonFile's content into 'users' which we defined above
|
||||
json.Unmarshal(byteValue, &p)
|
||||
|
||||
return nil
|
||||
}
|
||||
246
plugin/plugin_test.go
Normal file
246
plugin/plugin_test.go
Normal file
@@ -0,0 +1,246 @@
|
||||
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"
|
||||
)
|
||||
|
||||
// Test if the dummy plugin added is detected
|
||||
func TestDetectPlugins(t *testing.T) {
|
||||
_, 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
|
||||
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
|
||||
_,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()
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// 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"
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
// -------------------------- Main test cases -------------------------------
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
// 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 {
|
||||
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user