188 Commits

Author SHA1 Message Date
b82d56b8d0 added go release.yml file and removed test package 2021-11-26 11:29:39 +04:00
Akilan Selvacoumar
9d99875cb8 Merge pull request #77 from Akilan1999/plugin-auto
[Feature] Added new feature mapped ports taken are mentioned
2021-10-25 00:01:23 +04:00
f63696d9da Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation into plugin-auto 2021-10-24 23:36:32 +04:00
0144e59d71 added feature to detect if a port is used by a plugin or not 2021-10-24 23:36:23 +04:00
Akilan Selvacoumar
8be15ca19b Merge pull request #76 from farhansolodev/windows_compatibility
Added automated install for windows
2021-10-15 22:31:32 +04:00
Farhan Alvi
c5efee3932 Added automated install for windows 2021-10-15 22:29:15 +04:00
Akilan Selvacoumar
b325b848d1 Merge pull request #75 from farhansolodev/master
Implemented remove plugin functionality and added docs
2021-10-09 18:47:31 +04:00
Farhan Alvi
57cf1f984b Merge pull request #3 from farhansolodev/package-manager
Merge pull request #1 from Akilan1999/package-manager
2021-10-09 18:46:01 +04:00
Farhan Alvi
d7b7e6b84b Merge pull request #2 from Akilan1999/package-manager
Implemented remove plugin and docs functionality
2021-10-09 18:43:35 +04:00
eb1644367e Added docs for adding and removing plugins 2021-10-09 18:37:09 +04:00
ab2a0b28f9 Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation into package-manager 2021-10-09 18:03:12 +04:00
9f304d26c1 Implemented a package manager to remove plugins 2021-10-09 18:03:04 +04:00
56be275759 saving changes 2021-10-09 17:34:15 +04:00
a06e1be2bc added mode to detect if a port is used or not in a container 2021-10-08 12:37:48 +04:00
d45bc99be7 wrote a function to detect the number of plugins available for a plugin 2021-10-08 11:54:28 +04:00
Akilan Selvacoumar
dec76d254f Merge pull request #73 from Akilan1999/automaticports
Setting automatic ports
2021-10-03 23:07:47 +04:00
91b15e3bd7 added docs 2021-10-03 23:05:56 +04:00
9d8303d66c add functionality to automatically allocate ports to a plugin 2021-10-03 22:13:45 +04:00
2a7d8e154d plugin copied to tmp and executed from there 2021-10-03 17:18:03 +04:00
Farhan Alvi
519801d2c0 Merge pull request #1 from Akilan1999/package-manager
added code to clone package manager
2021-10-01 14:39:34 +04:00
fc5e834552 added code to clone package manager 2021-10-01 14:38:13 +04:00
Akilan Selvacoumar
be985942b9 Merge pull request #70 from Akilan1999/possibility-custom-variable
added the possiblility to add custom varaibles
2021-09-17 16:53:37 +04:00
1ca73faaed added the possiblility to add custom varaibles 2021-09-17 16:44:34 +04:00
Akilan Selvacoumar
5da700a9d0 Update GenerateImplementation.md 2021-08-31 23:50:54 +04:00
Akilan Selvacoumar
86a266b017 Merge pull request #69 from Akilan1999/customize-p2prc
Extension p2prc you create your own modification
2021-08-31 23:50:07 +04:00
e9cc304d02 Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation into customize-p2prc 2021-08-31 23:44:50 +04:00
6b43d94e8d added docs for generate module 2021-08-31 23:44:20 +04:00
Akilan Selvacoumar
64580fade0 Merge pull request #68 from cr2007/master
Adds a Discord Banner for more vivid display
2021-08-31 11:58:37 +04:00
CSK
ddf0879f90 Merge branch 'Akilan1999:master' into master 2021-08-30 22:24:58 +04:00
Chandrashekhar R
e9ce832893 Adds an official Discord Banner
Uses Discord's API to display the server details
As well as a hyperlink underneath it too
2021-08-30 22:24:30 +04:00
Akilan Selvacoumar
24b1a1f8b6 Merge pull request #67 from cr2007/master
Changes to `index.html`
2021-08-30 21:35:31 +04:00
Chandrashekhar R
f781cc28fc Multiple commits to meet **HTML5** standards
1. Adds <abbr> tags for abbrieviations
2. Adds <dfn> tag for definitions
3. Minor Edits here and there too
2021-08-30 18:38:22 +04:00
Chandrashekhar R
c83ebbe149 Adds a target attribute within all <a> tags
Opens all the hyperlinks in a new tab/window
2021-08-30 18:09:41 +04:00
9d69aed8ce added usage docs 2021-08-30 18:00:54 +04:00
65de9dda17 fixed errors with generate 2021-08-30 17:57:54 +04:00
c3a3a21132 fixing errors to ensure generate works 2021-08-30 16:59:33 +04:00
Chandrashekhar R
f0bdb44e7c Changed the <font> tag to <span>
Replaces <font> with <span> to add CSS properties to the text
Thereby meeting HTML5 standards
2021-08-30 16:58:35 +04:00
ce5b7aa1af saving current changes for project extension generation 2021-08-30 14:38:27 +04:00
e4b1aaf208 generator import change complete 2021-08-29 00:13:18 +04:00
5823cf2028 added function to get current go module and added test case 2021-08-28 23:32:05 +04:00
5c2b36c086 created test case for go.mod 2021-08-28 21:54:09 +04:00
8fd9ccfa2d added AST feature and test case 2021-08-28 21:46:36 +04:00
85bf56ec01 added generate function to the ClI 2021-08-27 14:01:06 +04:00
e5334cbd3c buit base functions 2021-08-25 13:27:31 +04:00
Akilan Selvacoumar
fd9d5e1419 Merge pull request #65 from FarazzShaikh/patch-1
Update README.md
2021-08-23 20:54:15 +04:00
Faraz Shaikh
111c5ef93c Update README.md 2021-08-23 18:05:37 +05:30
Akilan Selvacoumar
1a7035164b Merge pull request #64 from Akilan1999/executeGroups
Execute groups when running plugins
2021-08-23 14:28:18 +04:00
554b08d6be changed appropriate docs 2021-08-23 14:24:24 +04:00
8b95d05986 added p2prc execute group id or container ID to the cli 2021-08-23 14:21:10 +04:00
ab2bcb393b added test case for either executing group ID or container ID 2021-08-23 14:15:07 +04:00
4ed2e10ac3 added method to check if the ID belongs to a group or container 2021-08-22 18:49:49 +04:00
Akilan Selvacoumar
8a278239ba Merge pull request #63 from cr2007/patch-1
Creates CITATION.cff file
2021-08-21 22:52:23 +04:00
CSK
51e9e38122 Creates CITATION.cff file
Allows easy citation of the repository via the GitHub website
2021-08-21 10:06:12 +04:00
Akilan Selvacoumar
a047c630d7 Merge pull request #61 from Akilan1999/group
Group
2021-08-13 23:17:19 +04:00
6b4b028b6f add note for grouping containers 2021-08-13 23:16:08 +04:00
dab82ae3cf add note for grouping containers 2021-08-13 23:15:00 +04:00
e3088a36e1 added docs for grouping containers 2021-08-13 23:14:00 +04:00
7a9a6b7ac5 added trackcontainers to .gitignore 2021-08-13 22:55:00 +04:00
c7985ed318 fixed when container removed to be removed from the tracked list 2021-08-13 22:52:01 +04:00
a920ff749b intergrated cli functionality 2021-08-13 21:40:00 +04:00
1fe5db06c0 added functionality to remove containers from all groups based on the container ID provided 2021-08-12 20:29:11 +04:00
d288d1f2d6 added functionality to remove container from the group 2021-08-12 18:43:21 +04:00
e2f8df9dcb added functionality to add container to the group 2021-08-12 09:36:06 +04:00
707592195a added functionality to remove group 2021-08-12 00:51:59 +04:00
10e5c72c90 added possibility to add a new container group 2021-08-11 23:16:36 +04:00
Akilan Selvacoumar
fa61b70d41 Update README.md 2021-08-11 14:32:29 +04:00
Akilan Selvacoumar
b8aa24d49e Update README.md 2021-08-11 14:31:15 +04:00
Akilan Selvacoumar
7f3e0a466f Update README.md 2021-08-11 14:25:22 +04:00
Akilan Selvacoumar
7fd33ceb4c Update Installation.md 2021-08-08 13:07:11 +04:00
Akilan Selvacoumar
4c43ab77bb Merge pull request #59 from Akilan1999/cli-plugin
Added possibility to execute plugin from Cli
2021-08-08 00:40:25 +04:00
4e133ed789 added plugin flag to docs 2021-08-08 00:37:34 +04:00
5ff6702d9c added functionality to trigger ansibles from cli 2021-08-08 00:21:44 +04:00
Akilan Selvacoumar
af4b129bee Update README.md 2021-08-05 16:14:48 +04:00
Akilan Selvacoumar
b776b3e1e1 Create FUNDING.yml 2021-08-03 19:07:55 +04:00
Akilan Selvacoumar
47dc49867b Update P2PImplementation.md 2021-07-27 22:52:42 +04:00
Akilan Selvacoumar
340177e992 Update release-drafter.yml 2021-07-22 16:26:54 +04:00
Akilan Selvacoumar
e893674180 Merge pull request #56 from Akilan1999/Akilan1999-patch-1
Update release-drafter.yml
2021-07-22 16:22:36 +04:00
Akilan Selvacoumar
b8e2a0047f Update release-drafter.yml 2021-07-22 16:21:47 +04:00
Akilan Selvacoumar
7f48b7fb3d Merge pull request #55 from Akilan1999/ReleaseAction
added github action for draft creating a release
2021-07-22 16:17:27 +04:00
116cd7e0bd added github action for creating a release 2021-07-22 16:15:39 +04:00
Akilan Selvacoumar
3e6c3b8a18 Merge pull request #54 from Akilan1999/serverports
Updated website with new ip address
2021-07-22 15:42:52 +04:00
1411a5c0da updated website 2021-07-22 15:38:16 +04:00
Akilan Selvacoumar
1063fa5fd7 Merge pull request #53 from Akilan1999/serverports
changed back to default print when using IP tables
2021-07-22 15:26:50 +04:00
2aea584f8b Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation into serverports 2021-07-22 14:09:42 +04:00
088c9c5ba4 changed back to default print when using IP tables 2021-07-22 14:08:15 +04:00
Akilan Selvacoumar
3ca75a540b Merge pull request #52 from Akilan1999/serverports
Added possibility to run server on any port
2021-07-22 13:12:41 +04:00
4e0fd09d73 modified config file 2021-07-22 13:04:25 +04:00
Akilan Selvacoumar
c3647c2fe7 Merge pull request #51 from Akilan1999/default-docker-container-no-vnc
Reading default port information from a json file
2021-07-19 04:15:51 +04:00
a9f3d39bbb added docs regarding adding ports 2021-07-19 04:13:47 +04:00
fc87d95753 changed the version name 2021-07-19 04:02:20 +04:00
c22f73ad28 added possibility to allocate internal ports inside docker containers 2021-07-19 03:35:43 +04:00
e98f4119da ports structure 2021-07-19 00:50:00 +04:00
Akilan Selvacoumar
c42725743d Update ClientImplementation.md 2021-07-18 13:22:25 +04:00
Akilan Selvacoumar
1877420fc6 Update ClientImplementation.md 2021-07-18 13:22:06 +04:00
Akilan Selvacoumar
decb1c0e10 Update ClientImplementation.md 2021-07-18 13:21:53 +04:00
a416578702 added docs for tracking containers 2021-07-18 13:11:41 +04:00
489ffd6d0c added tracker to cli abd into add and remove container on the client side 2021-07-18 12:12:31 +04:00
51110c235b added function to remove container 2021-07-18 11:27:26 +04:00
726292a77d added function to add tracked container 2021-07-18 10:06:14 +04:00
92cd9fe1ab add track contianer to the config path 2021-07-17 12:32:49 +04:00
Akilan Selvacoumar
739c7305a8 Merge pull request #50 from Akilan1999/run-ansible
Plugin module implementation
2021-07-16 21:46:25 +04:00
75a4bed9d1 modified docs for plugin module 2021-07-16 21:44:07 +04:00
0131ce5765 added docs for the plugin implementation 2021-07-16 20:51:22 +04:00
326ebe1697 added install docs for plugins 2021-07-16 19:50:43 +04:00
b6d757d5e3 added docs to setup ansible 2021-07-16 18:28:41 +04:00
022558f740 modified test to create container and remove container for plugins 2021-07-16 18:14:42 +04:00
58b8af4b6e Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation into run-ansible 2021-07-16 17:33:19 +04:00
ef031c5b68 added make testcases 2021-07-16 17:32:52 +04:00
de14a5fb06 changed generate_test_case.sh 2021-07-16 17:29:54 +04:00
1a0184406d added make for test cases 2021-07-16 17:27:54 +04:00
0069308a2a added plugin to execute ansible code 2021-07-16 16:22:06 +04:00
378c8bb75e added test case for ansibles 2021-07-16 06:20:37 +04:00
Akilan Selvacoumar
a73469155f Update index.html 2021-07-15 07:06:09 +04:00
Akilan Selvacoumar
0a28f22c76 Update README.md 2021-07-15 06:46:30 +04:00
a3ddad6aca added basic code to execute ansibles 2021-07-14 23:59:17 +04:00
Akilan Selvacoumar
08f58a00c5 Merge pull request #48 from Akilan1999/plugins
Detection of plugins
2021-07-13 23:39:13 +04:00
0ecd8355b5 Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation into default-docker-container 2021-07-13 23:29:28 +04:00
63f570bb4f added plugin detected 2021-07-13 23:28:45 +04:00
02f72209dc added base code for plugin system 2021-07-13 23:18:54 +04:00
Akilan Selvacoumar
68228a6013 Merge pull request #45 from Akilan1999/default-docker-container
added fix in if statement to fix simple error when adding ipv6 address
2021-07-10 00:17:01 +04:00
ae2500ed4b added fix in if statement to fix simple error when adding ipv6 address 2021-07-10 00:05:31 +04:00
Akilan Selvacoumar
5be8778652 Merge pull request #44 from Akilan1999/gitignore-iptable
gitignore iptable
2021-07-08 23:27:00 +04:00
6dde485de1 add gitignore for iptable 2021-07-08 23:23:34 +04:00
c0f70e87f4 added .gitignore for iptable 2021-07-08 22:47:51 +04:00
Akilan Selvacoumar
6df72c4abb Create CNAME 2021-07-08 22:25:09 +04:00
Akilan Selvacoumar
26e6fd4ec2 Merge pull request #43 from Akilan1999/addwebsite
added index.html page
2021-07-08 22:22:28 +04:00
aabac388ba added index.html page 2021-07-08 22:21:42 +04:00
Akilan Selvacoumar
655c5de4ec Merge pull request #42 from Akilan1999/update-install-docs
updated installation docs
2021-07-08 20:57:54 +04:00
3e8a99b435 updated installation docs 2021-07-08 20:55:42 +04:00
Akilan Selvacoumar
5e7f540802 Merge pull request #41 from Akilan1999/ipv6-add-fix
fixed ipv6 dectection error
2021-07-08 19:46:09 +04:00
28620b61ad fixed ipv6 dectection error 2021-07-08 19:42:41 +04:00
Akilan Selvacoumar
6f6072f598 Merge pull request #39 from Akilan1999/addcliipv6
Cli for add server accepts ipv4 and ipv6 address
2021-07-06 15:36:28 +04:00
f7bae1100a added possibility to add ipv4 and ipv6 address 2021-07-06 15:34:18 +04:00
a0b63fa2ec uncomitted changes 2021-07-06 15:25:52 +04:00
Akilan Selvacoumar
5b90bf3168 Update Installation.md 2021-06-26 00:38:28 +04:00
Akilan Selvacoumar
d7780a916b Merge pull request #36 from Akilan1999/easy_cli_commands
added aliases
2021-06-25 22:35:31 +04:00
10f37a60a4 added aliases 2021-06-25 22:26:08 +04:00
Akilan Selvacoumar
2b76c16215 Merge pull request #35 from Akilan1999/viewinterfaces
adds ipv6 index to config and a cli command to view network interface
2021-06-25 22:08:43 +04:00
f4bd08b6bf adds ipv6 index to config and a cli command to view network interface 2021-06-25 22:06:07 +04:00
Akilan Selvacoumar
680f703326 Merge pull request #34 from Akilan1999/ipv6
P2PRC compatible with IPV6
2021-06-25 17:35:07 +04:00
2caa9d0aac f**k you ipv4 2021-06-25 17:29:08 +04:00
657577f583 added ipv6 compatability to other commands 2021-06-25 17:22:01 +04:00
21b9efc3a6 fix ipv6 bugs 2021-06-25 17:13:40 +04:00
9f8e6a1f04 added ip table compatible with ipv6 2021-06-25 14:30:57 +04:00
1eac752fa7 current implementation of ipv6 2021-06-25 01:03:20 +04:00
Akilan Selvacoumar
fbb3748fe4 Merge pull request #33 from Akilan1999/SpeedTestModuleBUG
fixed list slice error
2021-06-24 18:45:26 +04:00
0bdcaca087 fixed list slice error 2021-06-24 18:44:09 +04:00
4f10936664 changed to port forwarding 2021-06-18 15:53:13 +04:00
Akilan Selvacoumar
1f5d9e0af8 Merge pull request #29 from Akilan1999/networking-docker
temporary add for horovod
2021-06-18 15:41:07 +04:00
ca222af710 temporary add for horovod 2021-06-18 15:39:20 +04:00
Akilan Selvacoumar
28ed412cdf Merge pull request #28 from Akilan1999/add-nettools
added net tools
2021-06-18 14:58:50 +04:00
2765f4e81e added net tools 2021-06-18 14:57:02 +04:00
c9e6206a89 added new libararies to go.mod 2021-06-17 22:19:06 +04:00
29176b16ec fixed issues in MakeFile 2021-06-17 22:17:44 +04:00
Akilan Selvacoumar
0bf44cff4e Update README.md 2021-06-15 21:59:59 +04:00
Akilan Selvacoumar
2e9a5599b5 Merge pull request #24 from Akilan1999/horovod
Horovod added gpuhovorod docker files
2021-06-15 15:09:56 +04:00
Akilan Selvacoumar
6e089961bb Merge pull request #23 from Akilan1999/horovod
Horovod
2021-06-15 15:07:25 +04:00
Benjamin Jacob Reji
4ee45ebabd Merge branch 'horovod' of github.com:Akilan1999/p2p-rendering-computation into horovod 2021-06-15 15:07:23 +04:00
Benjamin Jacob Reji
c5d8769b17 Added gpuhorovod Dockerfiles 2021-06-15 15:06:44 +04:00
4c8d6ae28f Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation into horovod 2021-06-15 15:04:44 +04:00
02ca82084b fixed issue only 1 image running in GPU 2021-06-15 15:02:23 +04:00
Akilan Selvacoumar
9d03b08450 Merge pull request #22 from Akilan1999/horovod
Added horovod CPU image
2021-06-12 22:20:36 +04:00
1730a58e53 Intergrated horovod CPU with P2P network and added test cases 2021-06-12 22:15:18 +04:00
c9b35ac790 fixed errors when providing docker container name in the parameter 2021-06-11 01:52:31 +04:00
Akilan Selvacoumar
afab95db65 Update Installation.md 2021-06-10 22:42:27 +04:00
af46493aa9 added horovod cpu image 2021-06-10 16:04:53 +04:00
435f553889 minor changes 2021-06-10 15:40:50 +04:00
Akilan Selvacoumar
0495a49f90 Merge pull request #21 from Akilan1999/pass-through-docker-cotainer
Allow client to choose docker container to run on the server side
2021-06-10 15:18:40 +04:00
ad9a1c9699 added functionality to specify container to run 2021-06-10 01:42:16 +04:00
14bceec3cc added cli command view containers and implementation also complete 2021-06-09 23:59:46 +04:00
8466e2d1ca added code to detect docker containers 2021-06-09 16:43:59 +04:00
Akilan Selvacoumar
4141f1c575 Merge pull request #18 from Akilan1999/add-server-ip-address
added cli command add server
2021-06-08 21:55:19 +04:00
84be0012a1 added cli command add server 2021-06-08 21:52:08 +04:00
Akilan Selvacoumar
370544958d Update README.md 2021-06-06 07:48:01 +04:00
Akilan Selvacoumar
2cef7b4b35 Merge pull request #16 from Akilan1999/make-install-issue
fixed command issue in MakeFile
2021-06-06 07:46:28 +04:00
a46a7983c5 fixed command issue in MakeFile 2021-06-06 07:07:47 +04:00
Akilan Selvacoumar
8fbc644f72 Update README.md 2021-06-05 14:45:58 +04:00
Akilan Selvacoumar
49088aa44e Update README.md 2021-06-05 14:44:56 +04:00
Akilan Selvacoumar
0ae7546e05 Update README.md 2021-06-05 14:43:52 +04:00
Akilan Selvacoumar
de308898df Update README.md 2021-06-05 14:14:20 +04:00
Akilan Selvacoumar
dc890e2a67 Update README.md 2021-06-05 14:05:47 +04:00
Akilan Selvacoumar
bc643ba4a9 Update README.md 2021-06-05 14:02:40 +04:00
Akilan Selvacoumar
36b759d930 Update README.md 2021-06-05 14:01:49 +04:00
Akilan Selvacoumar
d1ee000ce7 Update README.md 2021-06-05 13:01:02 +04:00
Akilan Selvacoumar
780fcb119e Added logo 2021-06-05 12:56:40 +04:00
Akilan Selvacoumar
cc2b3fb879 Update README.md 2021-06-01 00:58:51 +04:00
Akilan Selvacoumar
cdb2a194d5 Update README.md 2021-06-01 00:48:51 +04:00
Akilan Selvacoumar
9d28f07ad2 Update README.md 2021-06-01 00:48:24 +04:00
183 changed files with 4887 additions and 2247 deletions

12
.github/FUNDING.yml vendored Normal file
View 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
View 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

15
.gitignore vendored
View File

@@ -7,4 +7,17 @@ server/docker/__pycache__
p2p-rendering-computation p2p-rendering-computation
p2prc p2prc
config.json config.json
.vscode/ .vscode/
#ignore generated iptables
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
View 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
View 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
CNAME Normal file
View File

@@ -0,0 +1 @@
p2prc.akilan.io

View File

@@ -1,10 +1,16 @@
# Client Module Implementation # Client Module Implementation
This section focuses in depth on how the client module works. To understand the architecture of ## Topics
the client module refer to section 4.2. The client module is incharge of communicating with 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 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. from peer to peer modules. The objective here is how the client module interacts with peer to peer module
The objective here is how the client module interacts with peer to peer module and server module. and server module.
### Updating the IP table ### Updating the IP table
The client module calls the peer to peer module to get the local IP table initially, Based on the 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 At the moment the username and password are hard coded from the server side for both SSH and
VNC. VNC.
To remove a container the client module only requires the server IP address and the container ID. 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.

View 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.

View File

@@ -15,4 +15,6 @@ the project is git.sr.ht/~akilan1999/p2p-rendering-computation.
## [Config Module](ConfigImplementation.md) ## [Config Module](ConfigImplementation.md)
## [Server Module](ServerImplementation.md) ## [Server Module](ServerImplementation.md)
## [Client Module](ClientImplementation.md) ## [Client Module](ClientImplementation.md)
## [P2P Module](P2PImplementation.md) ## [P2P Module](P2PImplementation.md)
## [Plugin Module](PluginImplementation.md)
## [Generate Module](GenerateImplementation.md)

View File

@@ -2,6 +2,11 @@
Over here we will cover the basic steps to get the server and client side running. Over here we will cover the basic steps to get the server and client side running.
## Alpha release install
https://github.com/Akilan1999/p2p-rendering-computation/releases/tag/v1.0.0-alpha
## Install from Github master branch
### Install Go lang ### Install Go lang
The entire the implementation of this project is done using Go lang. The entire the implementation of this project is done using Go lang.
Thus, we need go lang to compile to code to a binary file. Thus, we need go lang to compile to code to a binary file.
@@ -16,7 +21,8 @@ interact with the containers.
[Instructions to install docker GPU](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker) [Instructions to install docker GPU](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker)
```` ````
Do ensure that the docker command does not need sudo to run // Do ensure that the docker command does not need sudo to run
sudo chmod 666 /var/run/docker.sock
```` ````
### Build Project and install project ### Build Project and install project
@@ -26,6 +32,26 @@ into a single binary
make install make install
``` ```
#### 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}
```
### Set up configuration file
```
make configfile
```
Open the config file ```config.json``` and add the IPv6 address
if you have one.
### Test if binary works ### Test if binary works
``` ```
p2prc --help p2prc --help
@@ -36,7 +62,7 @@ NAME:
p2p-rendering-computation - p2p cli application to create and access VMs in other servers p2p-rendering-computation - p2p cli application to create and access VMs in other servers
USAGE: USAGE:
p2p-rendering-computation [global options] command [command options] [arguments...] p2prc [global options] command [command options] [arguments...]
VERSION: VERSION:
1.0.0 1.0.0
@@ -45,22 +71,162 @@ COMMANDS:
help, h Shows a list of commands or help for one command help, h Shows a list of commands or help for one command
GLOBAL OPTIONS: GLOBAL OPTIONS:
--Mode value Specifies mode of running (default: "client") [$P2P_MODE] --Server, -s Starts server (default: false) [$SERVER]
--UpdateServerList Update List of Server available based on servers iptables (default: false) [$UPDATE_SERVER_LIST] --UpdateServerList, --us Update List of Server available based on servers iptables (default: false) [$UPDATE_SERVER_LIST]
--ListServers List servers which can render tasks (default: false) [$LIST_SERVERS] --ListServers, --ls List servers which can render tasks (default: false) [$LIST_SERVERS]
--CreateVM value Creates Docker container on the selected server [$CREATE_VM] --AddServer value, --as value Adds server IP address to iptables [$ADD_SERVER]
--RemoveVM value Stop and Remove Docker container [$REMOVE_VM] --ViewImages value, --vi value View images available on the server IP address [$VIEW_IMAGES]
--ID value Docker Container ID [$ID] --CreateVM value, --touch value Creates Docker container on the selected server [$CREATE_VM]
--Ports value Number of ports to open for the Docker Container [$NUM_PORTS] --ContainerName value, --cn value Specifying the container run on the server side [$CONTAINER_NAME]
--GPU Create Docker Containers to access GPU (default: false) [$USE_GPU] --RemoveVM value, --rm value Stop and Remove Docker container [$REMOVE_VM]
--Specs value Specs of the server node [$SPECS] --ID value, --id value Docker Container ID [$ID]
--SetDefaultConfig Sets a default configuration file (default: false) [$SET_DEFAULT_CONFIG] --Ports value, -p value Number of ports to open for the Docker Container [$NUM_PORTS]
--help, -h show help (default: false) --GPU, --gpu Create Docker Containers to access GPU (default: false) [$USE_GPU]
--version, -v print the version (default: false) --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>
--------------
<br>
# Using basic commands
### Start as a server
Do ensure you have docker installed for this
```
p2prc -s
```
### View server Specification
```
p2prc --specs=<ip address>
```
### Run container
use the ```--gpu``` if you know the other machine has a gpu.
```
p2prc --touch=<server ip address> -p <number of ports> --gpu
```
### Remove container
The docker id is present in the output where you create a container
```
p2prc --rm=<server ip address> --id=<docker container id>
```
### Adding servers to ip table
```
p2prc --as=<server ip address you want to add>
```
### Update ip table
```
p2prc --us
```
### List Servers
```
p2prc --ls
```
### View Network interfaces
```
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 .```
#### Note: The steps on how to use the commands will be added later.

View File

@@ -23,6 +23,7 @@ path of the IP table json file is received from the configuration module.
"latency": "<latency>", "latency": "<latency>",
"download": "<download>", "download": "<download>",
"upload": "<upload>" "upload": "<upload>"
"port no": "<server port no>"
} }
] ]
} }

View 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.

View File

@@ -12,5 +12,7 @@
3. [Server Module](ServerImplementation.md) 3. [Server Module](ServerImplementation.md)
4. [Config Module](ConfigImplementation.md) 4. [Config Module](ConfigImplementation.md)
5. [Cli Module](CliImplementation.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)

View File

@@ -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 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. 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
]
}
```

BIN
Docs/images/p2prclogo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@@ -1,19 +1,10 @@
SHELL := /bin/bash SHELL := /bin/bash
install: install:
go build -o p2prc sh install.sh p2prc
echo '# Paths for p2p rendering and computation' >> ~/.bashrc
echo 'export P2PRC=${PWD}' >> ~/.bashrc
echo 'export path=${PWD}:$${PATH}' >> ~/.bashrc
source ~/.bashrc
./p2prc --SetDefaultConfig
testcases:
build: sh plugin/generate_test_case.sh
go build -o p2prc
config:
./p2p-rendering-computation --SetDefaultConfig
run: run:
go run main.go go run main.go

View File

@@ -1,13 +1,101 @@
# P2P rendering and computation <h1 align="center">
<br>
<a href=""><img src="https://raw.githubusercontent.com/Akilan1999/p2p-rendering-computation/master/Docs/images/p2prclogo.png" alt="p2prc" width="400"></a>
<br>
</h1>
[![IMAGE ALT TEXT](http://img.youtube.com/vi/LRv3NR2lu7I/0.jpg)](https://www.youtube.com/watch?v=LRv3NR2lu7I "Simple P2P Cli application for creating containers") <!-- seperator -->
[![GPLv2 license](https://img.shields.io/badge/License-GPLv2-blue.svg)](http://perso.crans.org/besson/LICENSE.html)
[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/Akilan1999/p2p-rendering-computation/graphs/commit-activity)
[![made-with-Go](https://img.shields.io/badge/Made%20with-Go-1f425f.svg)](http://golang.org)
[![GoDoc reference example](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/git.sr.ht/~akilan1999/p2p-rendering-computation)
The main aim of this project was to create a custom peer to peer network. The user acting as the The main aim of this project was to create a custom peer to peer network. The user acting as the
client has total flexibility on how to batch the tasks and the user acting as the server has complete 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. flexibility on tracking the container's usages and killing the containers at any point of time.
1. [Installation](Docs/Installation.md) ## Gophers talk
2. [Documentation](Docs/README.md) [![IMAGE ALT TEXT](https://i.ytimg.com/vi/ovcZLEhQxWk/hqdefault.jpg)](https://www.youtube.com/watch?v=ovcZLEhQxWk "P2PRC - Gophers monthly talk")
<br>
## Table of contents
1. [Introduction](#Introduction)
2. [Installation](#Installation.md)
3. [Design Architecture](#Design-Architecture)
4. [Implementation](#Implementation)
5. [Find out more](#Find-out-more)
<br>
## Introduction
This project aims to create a peer to peer (p2p) network, where a user can use the p2p network to act as a client (i.e sending tasks) or the server (i.e executing the tasks). A prototype application will be developed, which comes bundled with a p2p module and possible to execute docker containers or virtual environments across selected nodes.
### Objectives
- Background review on peer to peer network, virtual environments, decentralized rendering tools and tools to batch any sort of tasks.
- Creating p2p network
- Server to create a containerised environment
- The client node to run tasks on Server containerised node
[Read more on the introduction](Docs/Introduction.md)
<br>
## Installation from source
1. Ensure the Go compiler 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
```
- 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 and usage](Docs/Installation.md)
<br>
## Design Architecture
The design architecture was inspired and based on the linux kernel design. The project is segmented into various modules. Each module is responsible for certain tasks in the project. The modules are highly dependent on each other hence the entire codebase can be considered as a huge monolithic chuck which acts as its own library
[Read more on the Design Architecture](Docs/DesignArchtectureIntro.md)
<br>
## Implementation
The programming language used for this project was Golang. The reason Go lang was chosen was because it is a compiled language. The entire codebase is just a single binary file. When distributing to other linux distributing the only requirement would be the binary file to run the code. It is easy to write independant modules and be monolithic at the sametime using Go. Using Go.mod makes it very easy to handle external libraries and modularise code. The go.mod name for the project is git.sr.ht/~akilan1999/p2p-rendering-computation.
[Read more on the Implementation](Docs/Implementation.md)
<br>
## 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.
[![Support Server](https://discordapp.com/api/guilds/854397492795277322/widget.png?style=banner2)](https://discord.gg/b4nRGTjYqy)

View 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
}

View 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()
}
}

View File

@@ -12,12 +12,8 @@ import (
"os" "os"
) )
type IP struct {
Query string
}
// UpdateIpTable Does the following to update it's IP table // 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() config, err := config.ConfigInit()
if err != nil { if err != nil {
@@ -26,10 +22,24 @@ func UpdateIpTable(IpAddress string) error {
client := http.Client{} client := http.Client{}
resp, err := UploadMultipartFile(client,"http://"+IpAddress+":8088/IpTable","json",config.IPTable)
if err != nil { var resp []byte
version := p2p.Ip4or6(IpAddress)
if version == "version 6" {
resp, err = UploadMultipartFile(client,"http://[" + IpAddress + "]:" + serverPort + "/IpTable","json",config.IPTable)
if err != nil {
return err return err
}
} else {
resp, err = UploadMultipartFile(client,"http://" + IpAddress + ":" + serverPort + "/IpTable","json",config.IPTable)
if err != nil {
return err
}
}
if resp == nil {
return nil
} }
//resp, err := SendPostRequest("http://"+IpAddress+":8088/IpTable", //resp, err := SendPostRequest("http://"+IpAddress+":8088/IpTable",
@@ -59,6 +69,7 @@ func UpdateIpTable(IpAddress string) error {
// UpdateIpTableListClient updates IP tables (Default 3 hops) based on server information available // UpdateIpTableListClient updates IP tables (Default 3 hops) based on server information available
//on the ip tables //on the ip tables
func UpdateIpTableListClient() error { func UpdateIpTableListClient() error {
// Ensure that the IP Table has Node pingable // Ensure that the IP Table has Node pingable
err := p2p.LocalSpeedTestIpTable() err := p2p.LocalSpeedTestIpTable()
if err != nil { if err != nil {
@@ -69,61 +80,55 @@ func UpdateIpTableListClient() error {
// duplication // duplication
Addresses, err := p2p.ReadIpTable() Addresses, err := p2p.ReadIpTable()
var DoNotRead p2p.IpAddresses //var DoNotRead p2p.IpAddresses
// Run loop 3 times // Run loop 3 times
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
// Gets information from IP table // Gets information from IP table
Addresses, err = p2p.ReadIpTable() //Addresses, err = p2p.ReadIpTable()
if err != nil { //if err != nil {
return err // return err
} //}
//
// Appending current machine public IP address as should not be there in IP Table //DoNotRead.IpAddress = append(DoNotRead.IpAddress, PublicIP)
var PublicIP p2p.IpAddress
ip, err := CurrentPublicIP()
if err != nil {
return err
}
PublicIP.Ipv4 = ip
DoNotRead.IpAddress = append(DoNotRead.IpAddress, PublicIP)
// Updates IP table based on server IP table // Updates IP table based on server IP table
for j := range Addresses.IpAddress { for j := range Addresses.IpAddress {
Exists := false //Exists := false
//
//if PublicIP.Ipv4 == Addresses.IpAddress[j].Ipv4 || (PublicIP.Ipv6 != "" && Addresses.IpAddress[j].Ipv6 == PublicIP.Ipv6){
// Exists = true
//}
//
//// Check if IP addresses is there in the struct DoNotRead
//for k := range DoNotRead.IpAddress {
// if DoNotRead.IpAddress[k].Ipv4 == Addresses.IpAddress[j].Ipv4 || (DoNotRead.IpAddress[k].Ipv6 != "" && Addresses.IpAddress[j].Ipv6 == DoNotRead.IpAddress[k].Ipv6) {
// Exists = true
// break
// }
//}
//
//// If the struct exists then continues
//if Exists {
// continue
//}
if PublicIP.Ipv4 == Addresses.IpAddress[j].Ipv4 { if Addresses.IpAddress[j].Ipv6 != "" {
Exists = true err = UpdateIpTable(Addresses.IpAddress[j].Ipv6, Addresses.IpAddress[j].ServerPort)
} else {
err = UpdateIpTable(Addresses.IpAddress[j].Ipv4, Addresses.IpAddress[j].ServerPort)
} }
// Check if IP addresses is there in the struct DoNotRead
for k := range DoNotRead.IpAddress {
if DoNotRead.IpAddress[k].Ipv4 == Addresses.IpAddress[j].Ipv4 {
Exists = true
break
}
}
// If the struct exists then continues
if Exists {
continue
}
err = UpdateIpTable(Addresses.IpAddress[j].Ipv4)
if err != nil { if err != nil {
return err return err
} }
//Appends server1 IP address to variable DoNotRead //Appends server1 IP address to variable DoNotRead
DoNotRead.IpAddress = append(DoNotRead.IpAddress, Addresses.IpAddress[j]) //DoNotRead.IpAddress = append(DoNotRead.IpAddress, Addresses.IpAddress[j])
} }
} }
// Removing duplicates in the IP table
if err := p2p.RemoveDuplicates(); err != nil {
return err
}
return nil return nil
} }
@@ -216,6 +221,10 @@ func UploadMultipartFile(client http.Client, uri, key, path string) ([]byte, err
}() }()
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil {
return nil, err
}
content, err := ioutil.ReadAll(resp.Body) content, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
@@ -226,21 +235,3 @@ func UploadMultipartFile(client http.Client, uri, key, path string) ([]byte, err
} }
// CurrentPublicIP Get Current Public IP address
func CurrentPublicIP() (string,error) {
req, err := http.Get("http://ip-api.com/json/")
if err != nil {
return "",err
}
defer req.Body.Close()
body, err := ioutil.ReadAll(req.Body)
if err != nil {
return "",err
}
var ip IP
json.Unmarshal(body, &ip)
return ip.Query, nil
}

View File

@@ -3,6 +3,7 @@ package client
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"git.sr.ht/~akilan1999/p2p-rendering-computation/p2p"
"git.sr.ht/~akilan1999/p2p-rendering-computation/server" "git.sr.ht/~akilan1999/p2p-rendering-computation/server"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@@ -12,7 +13,20 @@ import (
// and other basic information which helps set a // and other basic information which helps set a
// cluster of computer // cluster of computer
func GetSpecs(IP string)(*server.SysInfo,error) { func GetSpecs(IP string)(*server.SysInfo,error) {
URL := "http://" + IP + ":" + serverPort + "/server_info" 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 {
URL = "http://" + IP + ":" + serverPort + "/server_info"
}
resp, err := http.Get(URL) resp, err := http.Get(URL)
if err != nil { if err != nil {
return nil,err return nil,err

220
client/TrackContainers.go Normal file
View 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
}

View 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()
}
}

View File

@@ -3,25 +3,39 @@ package client
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"git.sr.ht/~akilan1999/p2p-rendering-computation/p2p"
"git.sr.ht/~akilan1999/p2p-rendering-computation/server/docker" "git.sr.ht/~akilan1999/p2p-rendering-computation/server/docker"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strconv" "strconv"
) )
const ( var (
serverPort = "8088" serverPort = "8088"
client = http.Client{}
) )
var client = http.Client{}
// StartContainer Start container using REST api Implementation // StartContainer Start container using REST api Implementation
// From the selected server IP address // From the selected server IP address
// TODO: Test cases for this function // TODO: Test cases for this function
func StartContainer(IP string, NumPorts int, GPU bool) (*docker.DockerVM ,error) { //Calls URL ex: http://0.0.0.0:8088/startcontainer?ports=0&GPU=false&ContainerName=docker-ubuntu-sshd
func StartContainer(IP string, NumPorts int, GPU bool, ContainerName string) (*docker.DockerVM ,error) {
// Passes URL with number of TCP ports to allocated and to give GPU access to the docker container // Passes URL with number of TCP ports to allocated and to give GPU access to the docker container
URL := "http://" + IP + ":" + serverPort + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) 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 {
URL = "http://" + IP + ":" + serverPort + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) + "&ContainerName=" + ContainerName
}
resp, err := http.Get(URL) resp, err := http.Get(URL)
if err != nil { if err != nil {
return nil,err return nil,err
@@ -42,12 +56,31 @@ func StartContainer(IP string, NumPorts int, GPU bool) (*docker.DockerVM ,error)
return nil,err return nil,err
} }
// Adds the container to the tracked list
err = AddTrackContainer(&dockerResult, IP)
if err != nil {
return nil, err
}
return &dockerResult, nil return &dockerResult, nil
} }
// RemoveContianer Stops and removes container from the server // RemoveContianer Stops and removes container from the server
func RemoveContianer(IP string,ID string) error { func RemoveContianer(IP string,ID string) error {
URL := "http://" + IP + ":" + serverPort + "/RemoveContainer?id=" + ID 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 {
URL = "http://" + IP + ":" + serverPort + "/RemoveContainer?id=" + ID
}
resp, err := http.Get(URL) resp, err := http.Get(URL)
if err != nil { if err != nil {
return err return err
@@ -59,26 +92,101 @@ func RemoveContianer(IP string,ID string) error {
return err return err
} }
// Checks if success is returned in the body
if string(byteValue[:]) == "success" { if string(byteValue[:]) == "success" {
fmt.Println("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 return nil
} }
// PrintStartContainer Prints results Generated container // ViewContainers This function displays all containers available on server side
func PrintStartContainer(d *docker.DockerVM){ func ViewContainers(IP string)(*docker.DockerContainers, error){
fmt.Println("ID : " + fmt.Sprint(d.ID)) // Passes URL with route /ShowImages
fmt.Println("SSH port: " + fmt.Sprint(d.SSHPort)) var URL string
fmt.Println("SSH username: " + fmt.Sprint(d.SSHUsername)) version := p2p.Ip4or6(IP)
fmt.Println("SSH password: " + fmt.Sprint(d.SSHPassword))
fmt.Println("VNC port: " + fmt.Sprint(d.VNCPort)) //Get port number of the server
fmt.Println("VNC password: " + fmt.Sprint(d.VNCPassword)) serverPort, err := GetServerPort(IP)
fmt.Println("Ports Open (All TCP ports):") if err != nil {
for i := range d.Ports { return nil, err
fmt.Println(d.Ports[i])
} }
if version == "version 6" {
URL = "http://[" + IP + "]:" + serverPort + "/ShowImages"
} else {
URL = "http://" + IP + ":" + serverPort + "/ShowImages"
}
resp, err := http.Get(URL)
if err != nil {
return nil,err
}
// Convert response to byte value
byteValue, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil,err
}
// Create variable for result response type
var Result docker.DockerContainers
// Adds byte value to docker.DockerContainers struct
json.Unmarshal(byteValue, &Result)
if err != nil {
return nil,err
}
return &Result, nil
} }
// 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 // TODO implementation using RPC calls
//func StartContainer(Ip string) (*docker.DockerVM,error){ //func StartContainer(Ip string) (*docker.DockerVM,error){

View File

@@ -1,6 +1,8 @@
package client package client
import "testing" import (
"testing"
)
func TestUpdateIpTableListClient(t *testing.T) { func TestUpdateIpTableListClient(t *testing.T) {
err := UpdateIpTableListClient() err := UpdateIpTableListClient()
@@ -8,4 +10,5 @@ func TestUpdateIpTableListClient(t *testing.T) {
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
} }

View File

@@ -4,13 +4,15 @@ import (
"fmt" "fmt"
"git.sr.ht/~akilan1999/p2p-rendering-computation/client" "git.sr.ht/~akilan1999/p2p-rendering-computation/client"
"git.sr.ht/~akilan1999/p2p-rendering-computation/config" "git.sr.ht/~akilan1999/p2p-rendering-computation/config"
"git.sr.ht/~akilan1999/p2p-rendering-computation/generate"
"git.sr.ht/~akilan1999/p2p-rendering-computation/p2p" "git.sr.ht/~akilan1999/p2p-rendering-computation/p2p"
"git.sr.ht/~akilan1999/p2p-rendering-computation/plugin"
"git.sr.ht/~akilan1999/p2p-rendering-computation/server" "git.sr.ht/~akilan1999/p2p-rendering-computation/server"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
var CliAction = func(ctx *cli.Context) error { var CliAction = func(ctx *cli.Context) error {
if Mode == "server" { if Server {
// TODO: with RPC calls // TODO: with RPC calls
server.Server() server.Server()
//server.Rpc() //server.Rpc()
@@ -22,14 +24,72 @@ var CliAction = func(ctx *cli.Context) error {
if err != nil { if err != nil {
fmt.Print(err) 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() p2p.PrintIpTable()
} }
// Displays the IP table
if ServerList { 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() p2p.PrintIpTable()
} }
// Add provided IP to the IP table
if AddServer != "" {
res, err := p2p.ReadIpTable()
if err != nil {
fmt.Println(err)
}
//Create variable of type IpAddress and set IP address
// to it
var IpAddr p2p.IpAddress
//Checking if the address is a ipv4
// or ipv6 address
ip4Orip6 := p2p.Ip4or6(AddServer)
if ip4Orip6 == "version 6" {
IpAddr.Ipv6 = AddServer
} 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)
// Adds the new server IP to the iptable
res.WriteIpTable()
}
// Displays all images available on the server side
if ViewImages != "" {
imageRes, err := client.ViewContainers(ViewImages)
if err != nil {
fmt.Print(err)
}
client.PrettyPrint(imageRes)
}
// Function called to stop and remove server from Docker // Function called to stop and remove server from Docker
if RemoveVM != "" && ID != "" { if RemoveVM != "" && ID != "" {
err := client.RemoveContianer(RemoveVM,ID) err := client.RemoveContianer(RemoveVM,ID)
@@ -48,7 +108,8 @@ var CliAction = func(ctx *cli.Context) error {
fmt.Sscanf(Ports, "%d", &PortsInt) fmt.Sscanf(Ports, "%d", &PortsInt)
} }
imageRes, err := client.StartContainer(CreateVM,PortsInt,GPU) // Calls function to do Api call to start the container on the server side
imageRes, err := client.StartContainer(CreateVM,PortsInt,GPU,ContainerName)
if err != nil { if err != nil {
fmt.Print(err) fmt.Print(err)
@@ -75,6 +136,159 @@ var CliAction = func(ctx *cli.Context) error {
} }
} }
//If the network interface flag is called
// Then all the network interfaces are displayed
if NetworkInterface {
err := p2p.ViewNetworkInterface()
if err != nil {
fmt.Print(err)
}
}
// 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 return nil
} }

View File

@@ -6,79 +6,223 @@ import (
// Variables declared for CLI // Variables declared for CLI
var ( var (
CreateVM string AddServer string
Ports string ViewImages string
Mode string CreateVM string
RemoveVM string ContainerName string
ID string Ports string
Specs string Server bool
GPU bool RemoveVM string
UpdateServerList bool ID string
ServerList bool Specs string
SetDefaultConfig bool 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{ var AppConfigFlags = []cli.Flag{
// Deprecated to be implemented using GRPC // Deprecated to be implemented using GRPC
&cli.StringFlag{ &cli.BoolFlag{
Name: "Mode", Name: "Server",
Value: "client", Aliases: []string{"s"},
Usage: "Specifies mode of running", Usage: "Starts server",
EnvVars: []string{"P2P_MODE"}, EnvVars: []string{"SERVER"},
Destination: &Mode, Destination: &Server,
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: "UpdateServerList", Name: "UpdateServerList",
Aliases: []string{"us"},
Usage: "Update List of Server available based on servers iptables", Usage: "Update List of Server available based on servers iptables",
EnvVars: []string{"UPDATE_SERVER_LIST"}, EnvVars: []string{"UPDATE_SERVER_LIST"},
Destination: &UpdateServerList, Destination: &UpdateServerList,
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: "ListServers", Name: "ListServers",
Aliases: []string{"ls"},
Usage: "List servers which can render tasks", Usage: "List servers which can render tasks",
EnvVars: []string{"LIST_SERVERS"}, EnvVars: []string{"LIST_SERVERS"},
Destination: &ServerList, Destination: &ServerList,
}, },
&cli.StringFlag{
Name: "AddServer",
Aliases: []string{"as"},
Usage: "Adds server IP address to iptables",
EnvVars: []string{"ADD_SERVER"},
Destination: &AddServer,
},
&cli.StringFlag{
Name: "ViewImages",
Aliases: []string{"vi"},
Usage: "View images available on the server IP address",
EnvVars: []string{"VIEW_IMAGES"},
Destination: &ViewImages,
},
&cli.StringFlag{ &cli.StringFlag{
Name: "CreateVM", Name: "CreateVM",
Aliases: []string{"touch"},
Usage: "Creates Docker container on the selected server", Usage: "Creates Docker container on the selected server",
EnvVars: []string{"CREATE_VM"}, EnvVars: []string{"CREATE_VM"},
Destination: &CreateVM, Destination: &CreateVM,
}, },
&cli.StringFlag{
Name: "ContainerName",
Aliases: []string{"cn"},
Usage: "Specifying the container run on the server side",
EnvVars: []string{"CONTAINER_NAME"},
Destination: &ContainerName,
},
&cli.StringFlag{ &cli.StringFlag{
Name: "RemoveVM", Name: "RemoveVM",
Aliases: []string{"rm"},
Usage: "Stop and Remove Docker container", Usage: "Stop and Remove Docker container",
EnvVars: []string{"REMOVE_VM"}, EnvVars: []string{"REMOVE_VM"},
Destination: &RemoveVM, Destination: &RemoveVM,
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "ID", Name: "ID",
Aliases: []string{"id"},
Usage: "Docker Container ID", Usage: "Docker Container ID",
EnvVars: []string{"ID"}, EnvVars: []string{"ID"},
Destination: &ID, Destination: &ID,
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "Ports", Name: "Ports",
Aliases: []string{"p"},
Usage: "Number of ports to open for the Docker Container", Usage: "Number of ports to open for the Docker Container",
EnvVars: []string{"NUM_PORTS"}, EnvVars: []string{"NUM_PORTS"},
Destination: &Ports, Destination: &Ports,
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: "GPU", Name: "GPU",
Aliases: []string{"gpu"},
Usage: "Create Docker Containers to access GPU", Usage: "Create Docker Containers to access GPU",
EnvVars: []string{"USE_GPU"}, EnvVars: []string{"USE_GPU"},
Destination: &GPU, Destination: &GPU,
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "Specs", Name: "Specification",
Aliases: []string{"specs"},
Usage: "Specs of the server node", Usage: "Specs of the server node",
EnvVars: []string{"SPECS"}, EnvVars: []string{"SPECS"},
Destination: &Specs, Destination: &Specs,
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: "SetDefaultConfig", Name: "SetDefaultConfig",
Aliases: []string{"dc"},
Usage: "Sets a default configuration file", Usage: "Sets a default configuration file",
EnvVars: []string{"SET_DEFAULT_CONFIG"}, EnvVars: []string{"SET_DEFAULT_CONFIG"},
Destination: &SetDefaultConfig, Destination: &SetDefaultConfig,
}, },
&cli.BoolFlag{
Name: "NetworkInterfaces",
Aliases: []string{"ni"},
Usage: "Shows the network interface in your computer",
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,
},
} }

View File

@@ -2,26 +2,32 @@ package config
import ( import (
"github.com/spf13/viper" "github.com/spf13/viper"
"io"
"os" "os"
) )
var ( var (
defaultPath string defaultPath string
defaults = map[string]interface{}{ defaults = map[string]interface{}{}
"IPTable": "/etc/p2p-rendering/ip_table.json",
"DockerFile": "/home/akilan/Documents/p2prendering/p2p-redering-computation/server/docker/containers/docker-ubuntu-sshd/",
"SpeedTestFile":"/etc/p2p-rendering/50.bin",
}
configName = "config" configName = "config"
configType = "json" configType = "json"
configFile = "config.json" configFile = "config.json"
configPaths []string configPaths []string
defaultEnvName = "P2PRC"
) )
type Config struct { type Config struct {
IPTable string IPTable string
DockerFile string DockerContainers string
SpeedTestFile string DefaultDockerFile string
SpeedTestFile string
IPV6Address string
PluginPath string
TrackContainersPath string
ServerPort string
GroupTrackContainersPath string
//NetworkInterface string
//NetworkInterfaceIPV6Index int
} }
// Exists reports whether the named file or directory exists. // Exists reports whether the named file or directory exists.
@@ -34,19 +40,92 @@ func fileExists(name string) bool {
return true return true
} }
// Copy the src file to dst. Any existing file will be overwritten and will not
// copy file attributes.
// Source: https://stackoverflow.com/questions/21060945/simple-way-to-copy-a-file
func Copy(src, dst string) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, in)
if err != nil {
return err
}
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 // SetDefaults This function to be called only during a
// make install // make install
func SetDefaults() error { func SetDefaults() error {
//Getting Current Directory from environment variable
curDir := os.Getenv("P2PRC")
//Setting current directory to default path //Setting current directory to default path
defaultPath = curDir + "/" defaultPath, err := GetPathP2PRC()
if err != nil{
return err
}
//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
}
//Setting default paths for the config file //Setting default paths for the config file
defaults["IPTable"] = defaultPath + "p2p/ip_table.json" defaults["IPTable"] = defaultPath + "p2p/iptable/ip_table.json"
defaults["DockerFile"] = defaultPath + "server/docker/containers/docker-ubuntu-sshd/" defaults["DefaultDockerFile"] = defaultPath + "server/docker/containers/docker-ubuntu-sshd/"
defaults["DockerContainers"] = defaultPath + "server/docker/containers/"
defaults["SpeedTestFile"] = defaultPath + "p2p/50.bin" 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"
//Paths to search for config file //Paths to search for config file
configPaths = append(configPaths, defaultPath) configPaths = append(configPaths, defaultPath)
@@ -59,7 +138,7 @@ func SetDefaults() error {
} }
//Calling configuration file //Calling configuration file
_, err := ConfigInit() _, err = ConfigInit()
if err != nil { if err != nil {
return err return err
} }
@@ -68,9 +147,11 @@ func SetDefaults() error {
func ConfigInit()(*Config,error) { func ConfigInit()(*Config,error) {
curDir := os.Getenv("P2PRC")
//Setting current directory to default path //Setting current directory to default path
defaultPath = curDir + "/" defaultPath, err := GetPathP2PRC()
if err != nil{
return nil, err
}
//Paths to search for config file //Paths to search for config file
configPaths = append(configPaths, defaultPath) configPaths = append(configPaths, defaultPath)

View File

@@ -1,6 +1,8 @@
package config package config
import ( import (
"fmt"
"os"
"testing" "testing"
) )
@@ -17,3 +19,45 @@ func TestSetDefaults(t *testing.T) {
t.Error(err) 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)
}

View File

@@ -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.

View File

@@ -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://&lt;hostname&gt;: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

View 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.

View File

@@ -1,5 +0,0 @@
[defaults]
host_key_checking = False
[ssh_connection]
ssh_args = -o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s

View File

@@ -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

View File

@@ -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 }}"

View File

@@ -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

View File

@@ -1,5 +0,0 @@
---
# CUDA Driver Setup
- name: reboot the machine
reboot:
listen: "reboot the machine"

View File

@@ -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"

View File

@@ -1,3 +0,0 @@
---
- import_tasks: debian.yml
when: ansible_facts['os_family']|lower == 'debian' # debian, ubuntu

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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 }}"

View File

@@ -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

View File

@@ -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
```

View File

@@ -1,6 +0,0 @@
---
- name: reload the docker service
systemd:
name: docker
state: reloaded
listen: "reload the docker service"

View File

@@ -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"

View File

@@ -1,4 +0,0 @@
---
# Nvidia Docker Runtime Setup
- import_tasks: debian.yml
when: ansible_facts['os_family']|lower == 'debian' # debian, ubuntu

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,3 +0,0 @@
---
- import_tasks: debian.yml
when: ansible_facts['os_family']|lower == 'debian' # debian, ubuntu

View File

@@ -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

View File

@@ -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

View File

@@ -1,5 +0,0 @@
---
- name: restart the rsync service
systemd:
name: "{{ rsync.service_name }}"
state: restarted

View File

@@ -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

View File

@@ -1,10 +0,0 @@
---
rsync:
config_file:
src: rsyncd.conf
dest: /etc/rsyncd.conf
master: ml1
options:
- "-e ssh"
- "--no-motd"
service_name: rsync

View File

@@ -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
View 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
View 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)
}

View 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
View File

@@ -0,0 +1,9 @@
package generate
import (
"fmt"
)
func TestCaseAST() {
fmt.Println("lol")
}

11
go.mod
View File

@@ -5,32 +5,31 @@ go 1.15
require ( require (
github.com/Microsoft/hcsshim v0.8.15 // indirect github.com/Microsoft/hcsshim v0.8.15 // indirect
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // 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/containerd/continuity v0.0.0-20210315143101-93e15499afd5 // indirect
github.com/docker/docker v20.10.0-beta1.0.20201113105859-b6bfff2a628f+incompatible github.com/docker/docker v20.10.0-beta1.0.20201113105859-b6bfff2a628f+incompatible
github.com/docker/go-connections v0.4.0 github.com/docker/go-connections v0.4.0
github.com/gin-gonic/gin v1.6.3 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/go-ole/go-ole v1.2.5 // indirect
github.com/google/go-cmp v0.5.4 // indirect github.com/google/go-cmp v0.5.4 // indirect
github.com/google/uuid v1.1.2 github.com/google/uuid v1.1.2
github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/mux v1.8.0 // indirect
github.com/grandcat/zeroconf v1.0.0 // indirect
github.com/lithammer/shortuuid v3.0.0+incompatible github.com/lithammer/shortuuid v3.0.0+incompatible
github.com/moby/sys/mount v0.2.0 // indirect github.com/moby/sys/mount v0.2.0 // indirect
github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf // indirect github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf // indirect
github.com/morikuni/aec v1.0.0 // 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/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
github.com/shirou/gopsutil v3.20.12+incompatible 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/spf13/viper v1.4.0
github.com/urfave/cli/v2 v2.3.0 github.com/urfave/cli/v2 v2.3.0
gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 // indirect gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 // indirect
gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3 gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect golang.org/x/mod v0.3.0
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 // indirect
golang.org/x/text v0.3.5 // indirect golang.org/x/text v0.3.5 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
golang.org/x/tools v0.0.0-20210106214847-113979e3529a
google.golang.org/grpc v1.35.0 // 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 gotest.tools/v3 v3.0.3 // indirect
) )

117
go.sum
View File

@@ -35,13 +35,13 @@ github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3 h1:mw6pDQqv38/WGF1cO/jF5t/jyAJ2yi7CmtFLLO5tGFI= github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3 h1:mw6pDQqv38/WGF1cO/jF5t/jyAJ2yi7CmtFLLO5tGFI=
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
@@ -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/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/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/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/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/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/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 h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= 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-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/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-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-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/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/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/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/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= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -83,8 +96,6 @@ github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -162,11 +173,11 @@ github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= 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/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.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 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
@@ -204,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/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 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/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.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.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -211,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/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/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.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/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.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
@@ -223,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-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 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= 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 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-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -288,7 +315,6 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
@@ -327,8 +353,6 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE=
github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
@@ -348,14 +372,18 @@ 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.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.8/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.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/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/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-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/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= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -363,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/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/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/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.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.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@@ -372,15 +402,15 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 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/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 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.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.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5 h1:hyz3dwM5QLc1Rfoz4FuWJQG5BN7tc6K1MndAUnGpQr4=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= 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.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 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= 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= github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5nwm/V115vj2YXfhS0w=
@@ -391,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.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= 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/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.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.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 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
@@ -399,9 +432,8 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 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/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM=
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= 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/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 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
@@ -414,11 +446,9 @@ github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGq
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf h1:Un6PNx5oMK6CCwO3QTUyPiK2mtZnPrpDl5UnZ64eCkw= github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf h1:Un6PNx5oMK6CCwO3QTUyPiK2mtZnPrpDl5UnZ64eCkw=
github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
@@ -430,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/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/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/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/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/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= github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -452,7 +483,6 @@ github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
@@ -466,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/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.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= 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 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 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= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
@@ -514,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/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/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/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 h1:6VEGkOXP/eP4o2Ilk8cSsX0PhOEfX6leqAnD+urrp9M=
github.com/shirou/gopsutil v3.20.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= 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 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 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= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
@@ -558,10 +596,10 @@ github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRci
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 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.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-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-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@@ -586,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/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-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= 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/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/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= github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
@@ -616,16 +656,18 @@ 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-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-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-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-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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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-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-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-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -655,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.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.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.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/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-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -676,7 +719,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -689,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-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-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-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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/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-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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -703,7 +746,6 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -730,7 +772,6 @@ golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -759,19 +800,20 @@ golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-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-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-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/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.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
@@ -808,7 +850,6 @@ golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
@@ -820,7 +861,6 @@ golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a h1:CB3a9Nez8M13wwlr/E2YtwoU+qYHKfC+JrDa45RXXoQ=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -864,7 +904,6 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8=
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@@ -898,10 +937,11 @@ gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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-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/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
@@ -912,13 +952,14 @@ 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.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/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/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.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.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=

61
index.html Normal file
View File

@@ -0,0 +1,61 @@
<html>
<head>
<title>P2PRC</title>
<style>
body { font-family: sans-serif; }
</style>
</head>
<body>
<img src="Docs/images/p2prclogo.png" alt="P2PRC Logo">
<h1>P2PRC</h1>
<b>A peer to peer network designed for computation</b>
<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" 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>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>
<p><b>Main developer:</b></p>
<ul>
<li>
<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" 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>

6
install.bat Normal file
View File

@@ -0,0 +1,6 @@
go build -o p2prc.exe
setx PATH "%PATH%;%cd%"
setx P2PRC "%cd%"
p2prc --dc

11
install.sh Normal file
View 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

View File

@@ -8,7 +8,7 @@ import (
) )
// VERSION specifies the version of the platform // VERSION specifies the version of the platform
var VERSION = "1.0.0" var VERSION = "1.5.0"
var mode string var mode string
// Varaibles if mode is client // Varaibles if mode is client

View File

@@ -1,3 +1,12 @@
{ {
"ip_address": null "ip_address": [
{
"ipv4": "139.162.246.221",
"ipv6": "",
"latency": 0,
"download": 0,
"upload": 0,
"serverport": "8088"
}
]
} }

View File

@@ -5,6 +5,8 @@ import (
"fmt" "fmt"
"git.sr.ht/~akilan1999/p2p-rendering-computation/config" "git.sr.ht/~akilan1999/p2p-rendering-computation/config"
"io/ioutil" "io/ioutil"
"net"
"net/http"
"os" "os"
"time" "time"
) )
@@ -17,9 +19,15 @@ type IpAddresses struct {
type IpAddress struct { type IpAddress struct {
Ipv4 string `json:"ipv4"` Ipv4 string `json:"ipv4"`
Ipv6 string `json:"ipv6"`
Latency time.Duration `json:"latency"` Latency time.Duration `json:"latency"`
Download float64 `json:"download"` Download float64 `json:"download"`
Upload float64 `json:"upload"` Upload float64 `json:"upload"`
ServerPort string `json:"serverport"`
}
type IP struct {
Query string
} }
// ReadIpTable Read data from Ip tables from json file // ReadIpTable Read data from Ip tables from json file
@@ -49,11 +57,39 @@ func ReadIpTable()(*IpAddresses ,error){
// jsonFile's content into 'users' which we defined above // jsonFile's content into 'users' which we defined above
json.Unmarshal(byteValue, &ipAddresses) json.Unmarshal(byteValue, &ipAddresses)
var PublicIP IpAddress
ipv6, err := GetCurrentIPV6()
if err != nil {
return nil, err
}
ip, err := CurrentPublicIP()
if err != nil {
return nil, err
}
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)
//before writing to iptable ensures the duplicates are removed
if err = ipAddresses.RemoveDuplicates(); err != nil {
return nil, err
}
return &ipAddresses, nil return &ipAddresses, nil
} }
// WriteIpTable Write to IP table json file // WriteIpTable Write to IP table json file
func (i *IpAddresses) WriteIpTable() error { func (i *IpAddresses) WriteIpTable() error {
//before writing to iptable ensures the duplicates are removed
if err := i.RemoveDuplicates(); err != nil {
return err
}
file, err := json.MarshalIndent(i, "", " ") file, err := json.MarshalIndent(i, "", " ")
if err != nil { if err != nil {
return err return err
@@ -82,40 +118,121 @@ func PrintIpTable() error {
} }
for i := 0; i < len(table.IpAddress); i++ { for i := 0; i < len(table.IpAddress); i++ {
fmt.Printf("\nIP Address: %s\nLatency: %s\n-----------" + fmt.Printf("\nIP Address: %s\nIPV6: %s\nLatency: %s\nServerPort: %s\n-----------" +
"-----------------\n",table.IpAddress[i].Ipv4, "-----------------\n",table.IpAddress[i].Ipv4,table.IpAddress[i].Ipv6,
table.IpAddress[i].Latency) table.IpAddress[i].Latency, table.IpAddress[i].ServerPort)
} }
return nil return nil
} }
// RemoveDuplicates This is a temporary fix current functions failing to remove // RemoveDuplicates This is a temporary fix current functions failing to remove
// Duplicate IP addresses from local IP table // Duplicate IP addresses from local IP table
func RemoveDuplicates() error { func (table *IpAddresses)RemoveDuplicates() error {
table, err := ReadIpTable()
if err != nil {
return err
}
var NoDuplicates IpAddresses var NoDuplicates IpAddresses
for i, _:= range table.IpAddress { for i, _:= range table.IpAddress {
Exists := false Exists := false
for k := range NoDuplicates.IpAddress { for k := range NoDuplicates.IpAddress {
if NoDuplicates.IpAddress[k].Ipv4 == table.IpAddress[i].Ipv4 { if (NoDuplicates.IpAddress[k].Ipv4 != "" && NoDuplicates.IpAddress[k].Ipv4 == table.IpAddress[i].Ipv4) || (NoDuplicates.IpAddress[k].Ipv6 != "" && NoDuplicates.IpAddress[k].Ipv6 == table.IpAddress[i].Ipv6) {
Exists = true Exists = true
break break
} }
} }
if Exists { if Exists {
continue continue
} }
NoDuplicates.IpAddress = append(NoDuplicates.IpAddress, table.IpAddress[i]) NoDuplicates.IpAddress = append(NoDuplicates.IpAddress, table.IpAddress[i])
} }
if err := NoDuplicates.WriteIpTable(); err != nil { table.IpAddress = NoDuplicates.IpAddress
return nil
}
return nil return nil
}
// CurrentPublicIP Get Current Public IP address
func CurrentPublicIP() (string,error) {
req, err := http.Get("http://ip-api.com/json/")
if err != nil {
return "",err
}
defer req.Body.Close()
body, err := ioutil.ReadAll(req.Body)
if err != nil {
return "",err
}
var ip IP
json.Unmarshal(body, &ip)
return ip.Query, nil
}
// GetCurrentIPV6 gets the current IPV6 address based on the interface
// specified in the config file
func GetCurrentIPV6()(string,error){
Config, err := config.ConfigInit()
if err != nil {
return "",err
}
// Fix in future release
//byNameInterface, err := net.InterfaceByName(Config.NetworkInterface)
//if err != nil {
// return "",err
//}
//addresses, err := byNameInterface.Addrs()
//if err != nil {
// return "",err
//}
//if addresses[1].String() == "" {
// return "",errors.New("IPV6 address not detected")
//}
//IP,_,err := net.ParseCIDR(addresses[Config.NetworkInterfaceIPV6Index].String())
//if err != nil {
// return "",err
//}
return Config.IPV6Address, nil
}
// ViewNetworkInterface This function is created to view the network interfaces available
func ViewNetworkInterface() error {
ifaces, err := net.Interfaces()
if err != nil {
return err
}
for _, i := range ifaces {
addrs, err := i.Addrs()
if err != nil {
return err
}
for index, a := range addrs {
switch v := a.(type) {
case *net.IPAddr:
fmt.Printf("(%v) %v : %s (%s)\n", index, i.Name, v, v.IP.DefaultMask())
case *net.IPNet:
fmt.Printf("(%v) %v : %s \n", index, i.Name, v)
}
}
}
return nil
}
// Ip4or6 Helper function to check if the IP address is IPV4 or
//IPV6 (https://socketloop.com/tutorials/golang-check-if-ip-address-is-version-4-or-6)
func Ip4or6(s string) string {
for i := 0; i < len(s); i++ {
switch s[i] {
case '.':
return "version 4"
case ':':
return "version 6"
}
}
return "version 6"
} }

View File

@@ -1,6 +1,7 @@
package p2p package p2p
import ( import (
"fmt"
"testing" "testing"
) )
@@ -20,3 +21,57 @@ func TestReadIpTable(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
} }
// Testing is a IPV6 address is returned
func TestGetCurrentIPV6(t *testing.T) {
res, err := GetCurrentIPV6()
if err != nil {
t.Error(err)
}
fmt.Println(res)
}
// This test ensures that the duplicate function works as intended
func TestIpAddresses_RemoveDuplicates(t *testing.T) {
var testduplicates IpAddresses
var duplicateaddress1 IpAddress
var duplicateaddress2 IpAddress
duplicateaddress1.Ipv6="2001:8f8:172d:ee93:7588:ad57:c351:3309"
duplicateaddress1.Ipv4="0.0.0.0"
duplicateaddress2.Ipv6="2001:8f8:172d:ee93:7588:ad57:c351:3309"
duplicateaddress2.Ipv4="0.0.0.0"
testduplicates.IpAddress = append(testduplicates.IpAddress, duplicateaddress1)
testduplicates.IpAddress = append(testduplicates.IpAddress, duplicateaddress2)
err := testduplicates.RemoveDuplicates()
if err != nil {
t.Error(err)
}
if len(testduplicates.IpAddress) == 2 {
t.Fail()
}
}
func TestViewNetworkInterface(t *testing.T) {
err := ViewNetworkInterface()
if err != nil {
t.Error()
}
}
func TestIp4or6(t *testing.T) {
// This test ensures that the ipv6 address gets detected
test := "2001:8f8:172d:7e27:4f23:ae4:bce5:e037"
res := Ip4or6(test)
if res != "version 6" {
t.Fail()
}
}

View File

@@ -2,10 +2,13 @@ package p2p
// SpeedTest Runs a speed test and does updates IP tables accordingly // SpeedTest Runs a speed test and does updates IP tables accordingly
func (ip *IpAddresses)SpeedTest() error{ func (ip *IpAddresses)SpeedTest() error{
//temp variable to store elements IP addresses and other information
// of IP addresses that are pingable
var ActiveIP IpAddresses
// Index to remove from struct // Index to remove from struct
var RemoveIndex []int for _, value := range ip.IpAddress {
for i, value := range ip.IpAddress {
var err error var err error
//if len(ip.IpAddress) == 1 { //if len(ip.IpAddress) == 1 {
@@ -16,10 +19,6 @@ func (ip *IpAddresses)SpeedTest() error{
err = value.PingTest() err = value.PingTest()
if err != nil { if err != nil {
RemoveIndex = append(RemoveIndex, i)
// Record index to remove
//ip.IpAddress = append(ip.IpAddress[:i], ip.IpAddress[i+1:]...)
// Proceed to next element in the array
continue continue
} }
@@ -35,19 +34,12 @@ func (ip *IpAddresses)SpeedTest() error{
//} //}
//Set value to the list //Set value to the list
ip.IpAddress[i] = value
ActiveIP.IpAddress = append(ActiveIP.IpAddress, value)
} }
// Remove element from struct
for _, index := range RemoveIndex { ip.IpAddress = ActiveIP.IpAddress
// If there is only 1 element and that has to be
// removed
if len(ip.IpAddress) == 1 {
ip.IpAddress = nil
break
}
ip.IpAddress = append(ip.IpAddress[:index], ip.IpAddress[index+1:]...)
}
err := ip.WriteIpTable() err := ip.WriteIpTable()
if err != nil { if err != nil {
@@ -57,7 +49,7 @@ func (ip *IpAddresses)SpeedTest() error{
return nil return nil
} }
// SpeedTestUpdatedIPTable Called when ip tables from client/server is also passed on // SpeedTestUpdatedIPTable Called when ip tables from httpclient/server is also passed on
func (ip *IpAddresses)SpeedTestUpdatedIPTable() error{ func (ip *IpAddresses)SpeedTestUpdatedIPTable() error{
targets, err := ReadIpTable() targets, err := ReadIpTable()
if err != nil { if err != nil {
@@ -71,18 +63,20 @@ func (ip *IpAddresses)SpeedTestUpdatedIPTable() error{
for i, _ := range targets.IpAddress { for i, _ := range targets.IpAddress {
// To ensure that there are no duplicate IP addresses // To ensure that there are no duplicate IP addresses
Exists := false //Exists := false
for k := range ip.IpAddress { //for k := range ip.IpAddress {
if ip.IpAddress[k].Ipv4 == targets.IpAddress[i].Ipv4 { // // Checks if both the IPV4 addresses are the same or the IPV6 address is not
Exists = true // // an empty string and IPV6 address are the same
break // if ip.IpAddress[k].Ipv4 == targets.IpAddress[i].Ipv4 || (targets.IpAddress[i].Ipv6 != "" && ip.IpAddress[k].Ipv6 == targets.IpAddress[i].Ipv6) {
} // Exists = true
} // break
// }
// If the struct exists then continues //}
if Exists { //
continue //// If the struct exists then continues
} //if Exists {
// continue
//}
ip.IpAddress = append(ip.IpAddress, targets.IpAddress[i]) ip.IpAddress = append(ip.IpAddress, targets.IpAddress[i])
} }
@@ -111,6 +105,7 @@ func LocalSpeedTestIpTable() error {
return nil return nil
} }
// Helper function to remove element from an array of a struct // Helper function to remove element from an array of a struct
//func remove(s []IpAddress, i int) []IpAddress { //func remove(s []IpAddress, i int) []IpAddress {
// s[len(s)-1], s[i] = s[i], s[len(s)-1] // s[len(s)-1], s[i] = s[i], s[len(s)-1]

View File

@@ -1,21 +0,0 @@
package main
import (
"fmt"
"github.com/showwin/speedtest-go/speedtest"
)
func main() {
user, _ := speedtest.FetchUserInfo()
serverList, _ := speedtest.FetchServerList(user)
targets, _ := serverList.FindServer([]int{})
for _, s := range targets {
s.PingTest()
s.DownloadTest(false)
s.UploadTest(false)
fmt.Printf("Latency: %s, Download: %f, Upload: %f\n", s.Latency, s.DLSpeed, s.ULSpeed)
}
}

View File

@@ -14,7 +14,7 @@ import (
//var dlSizes = [...]int{350, 500, 750, 1000, 1500, 2000, 2500, 3000, 3500, 4000} //var dlSizes = [...]int{350, 500, 750, 1000, 1500, 2000, 2500, 3000, 3500, 4000}
//var ulSizes = [...]int{100, 300, 500, 800, 1000, 1500, 2500, 3000, 3500, 4000} //kB //var ulSizes = [...]int{100, 300, 500, 800, 1000, 1500, 2500, 3000, 3500, 4000} //kB
var client = http.Client{} var httpclient = http.Client{}
// DownloadTest executes the test to measure download speed // DownloadTest executes the test to measure download speed
//func (s *IpAddress) DownloadTest(savingMode bool) error { //func (s *IpAddress) DownloadTest(savingMode bool) error {
@@ -80,7 +80,7 @@ var client = http.Client{}
// Download Speed // Download Speed
func (s *IpAddress)DownloadSpeed() error { func (s *IpAddress)DownloadSpeed() error {
start := time.Now() start := time.Now()
resp, err := client.Get("http://" + s.Ipv4 + ":8088/50") resp, err := httpclient.Get("http://" + s.Ipv4 + ":8088/50")
if err != nil { if err != nil {
return err return err
} }
@@ -105,7 +105,7 @@ func (s *IpAddress)UploadSpeed() error {
b, w := createMultipartFormData("file",config.SpeedTestFile) 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 { if err != nil {
return err return err
} }
@@ -150,7 +150,14 @@ func mustOpen(f string) *os.File {
// PingTest executes test to measure latency // PingTest executes test to measure latency
func (s *IpAddress) PingTest() error { func (s *IpAddress) PingTest() error {
//pingURL := strings.Split(s.URL, "/upload")[0] + "/latency.txt" //pingURL := strings.Split(s.URL, "/upload")[0] + "/latency.txt"
pingURL := "http://" + s.Ipv4 + ":8088/server_info" var pingURL string
if s.Ipv6 != "" {
pingURL = "http://[" + s.Ipv6 + "]:" + s.ServerPort + "/server_info"
s.Ipv4 = ""
} else {
pingURL = "http://" + s.Ipv4 + ":" + s.ServerPort + "/server_info"
}
l := time.Duration(100000000000) // 10sec l := time.Duration(100000000000) // 10sec
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
sTime := time.Now() sTime := time.Now()

View File

@@ -1,21 +0,0 @@
package p2p
import(
"testing"
)
func TestAddRemoveUpnp(t *testing.T){
// forwarding port 23241 via upnp
err := ForwardPort(23241)
if err != nil {
t.Errorf("Error returned: %q", err)
}
// unforwarding port 23241 via upnp
err = UnForwardPort(23241)
if err != nil {
t.Errorf("Error returned: %q", err)
}
}

3
plugin/.dockerignore Normal file
View File

@@ -0,0 +1,3 @@
.idea
.DS_Store
Dockerfile

2
plugin/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.idea
.DS_Store

102
plugin/README.md Normal file
View 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
[![Laplace for gaming](./doc/laplace-for-gaming.png)](https://youtu.be/E8cUaPrAlzE)
## Try Demo
For demo, you can visit https://laplace.madeby.monster/
![Website screenshot](./doc/screenshot-website.png)
## 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/)

Some files were not shown because too many files have changed in this diff Show More