-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from DeFacto-Team/develop
Alpha release
- Loading branch information
Showing
8 changed files
with
552 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,62 @@ | ||
# Factom Network Restart System | ||
Restart system for Factom network | ||
The app connects to remote Portainer server via Portainer API and asynchronously restarts all containers with label `name=factomd`. | ||
|
||
## Configuration | ||
Config file with Portainer credentials should be placed in `~/.factom-restart/config.yaml` or provided as a flag `-c /path/to/config.yaml` while running the application. | ||
|
||
## Usage | ||
### Dry-run | ||
Run in dry-run mode (scans Portainer endpoints and containers, no restart happens): | ||
```bash | ||
go run . | ||
``` | ||
Output: | ||
```bash | ||
2020/09/15 13:49:01 Using config: /Users/anton/.factom-restart/config.yaml | ||
2020/09/15 13:49:01 Starting restart system | ||
2020/09/15 13:49:01 Portainer endpoint: https://test.com | ||
2020/09/15 13:49:01 DRY RUN mode: simulating restart | ||
2020/09/15 13:49:01 Successfully logged in as anton | ||
------------------------------ | ||
2020/09/15 13:49:01 Trying connecting to X (xxx.xxx.xxx.xxx), ID=2 | ||
2020/09/15 13:49:01 Empty response received from Portainer API | ||
------------------------------ | ||
2020/09/15 13:49:02 Trying connecting to Y (yyy.yyy.yyy.yyy), ID=29 | ||
2020/09/15 13:49:02 factomd container is running | ||
307f871a97e1dd91851c6298cf3a183f1709d908810b0059ce9094622bb78126 | ||
v6.6.0-alpine | ||
… | ||
------------------------------ | ||
2020/09/15 13:49:05 SIMULATING RESTART (DRY-RUN) | ||
2020/09/15 13:49:05 SKIP X | ||
2020/09/15 13:49:05 OK Y (307f871a97e1dd91851c6298cf3a183f1709d908810b0059ce9094622bb78126) | ||
… | ||
``` | ||
|
||
### Live mode | ||
Run in live mode (restarts the network): | ||
```bash | ||
go run . --live | ||
``` | ||
Output: | ||
```bash | ||
2020/09/15 13:49:01 Using config: /Users/anton/.factom-restart/config.yaml | ||
2020/09/15 13:49:01 Starting restart system | ||
2020/09/15 13:49:01 Portainer endpoint: https://test.com | ||
2020/09/15 13:49:01 LIVE mode: network will be restarted | ||
2020/09/15 13:49:01 Successfully logged in as anton | ||
------------------------------ | ||
2020/09/15 13:49:01 Trying connecting to X (xxx.xxx.xxx.xxx), ID=2 | ||
2020/09/15 13:49:01 Empty response received from Portainer API | ||
------------------------------ | ||
2020/09/15 13:49:02 Trying connecting to Y (yyy.yyy.yyy.yyy), ID=29 | ||
2020/09/15 13:49:02 factomd container is running | ||
307f871a97e1dd91851c6298cf3a183f1709d908810b0059ce9094622bb78126 | ||
v6.6.0-alpine | ||
… | ||
------------------------------ | ||
2020/09/15 13:49:05 RESTARTING NOW | ||
2020/09/15 13:49:05 SKIP X | ||
2020/09/15 13:49:05 OK Y (307f871a97e1dd91851c6298cf3a183f1709d908810b0059ce9094622bb78126) | ||
… | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
endpoint: https://test.factom.com | ||
username: test | ||
password: test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/jinzhu/configor" | ||
"github.com/mcuadros/go-defaults" | ||
) | ||
|
||
// App config struct | ||
type Config struct { | ||
Endpoint string `default:"" json:"endpoint" form:"endpoint" query:"endpoint" required:"true"` | ||
Username string `default:"" json:"username" form:"username" query:"username" required:"true"` | ||
Password string `default:"" json:"password" form:"password" query:"password" required:"true"` | ||
} | ||
|
||
// Create config from configFile | ||
func NewConfig(configFile string) (*Config, error) { | ||
|
||
config := new(Config) | ||
defaults.SetDefaults(config) | ||
|
||
if err := configor.Load(config, configFile); err != nil { | ||
return nil, err | ||
} | ||
return config, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module github.com/DeFacto-Team/factom-network-restart | ||
|
||
go 1.14 | ||
|
||
require ( | ||
github.com/jinzhu/configor v1.2.0 | ||
github.com/mcuadros/go-defaults v1.2.0 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= | ||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | ||
github.com/jinzhu/configor v1.2.0 h1:u78Jsrxw2+3sGbGMgpY64ObKU4xWCNmNRJIjGVqxYQA= | ||
github.com/jinzhu/configor v1.2.0/go.mod h1:nX89/MOmDba7ZX7GCyU/VIaQ2Ar2aizBl2d3JLF/rDc= | ||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | ||
github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk56oZtc= | ||
github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY= | ||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= | ||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"log" | ||
"os/user" | ||
"path/filepath" | ||
"strings" | ||
"sync" | ||
) | ||
|
||
const ( | ||
ColorRed = "\033[31m" | ||
ColorReset = "\033[0m" | ||
ColorYellow = "\033[33m" | ||
ColorBlue = "\033[34m" | ||
) | ||
|
||
func main() { | ||
|
||
var live bool | ||
var conf *Config | ||
|
||
usr, err := user.Current() | ||
if err != nil { | ||
log.Println(err) | ||
} | ||
|
||
// default config location | ||
configFile := filepath.Join(usr.HomeDir, ".factom-restart/config.yaml") | ||
|
||
// check if custom config location passed as flag | ||
flag.StringVar(&configFile, "c", configFile, "config.yaml path") | ||
|
||
// parse dry run flag | ||
flag.BoolVar(&live, "live", false, "live bool") | ||
|
||
flag.Parse() | ||
|
||
log.Printf("Using config: %s\n", configFile) | ||
|
||
// load config | ||
if conf, err = NewConfig(configFile); err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
log.Printf("Starting restart system\n") | ||
log.Printf("Portainer endpoint: %s\n", conf.Endpoint) | ||
|
||
if live { | ||
log.Println(string(ColorYellow), "LIVE mode: network will be restarted!", string(ColorReset)) | ||
} else { | ||
log.Println(string(ColorBlue), "DRY RUN mode: simulating restart", string(ColorReset)) | ||
} | ||
|
||
// initialize portainer | ||
p := NewPortainer(conf.Username, conf.Password, conf.Endpoint) | ||
|
||
// get all endpoints from portainer | ||
endpoints, err := p.GetSwarmEndpoints() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
// get factomd containers for each endpoint | ||
for i := range endpoints { | ||
if endpoints[i].PublicURL != "" { | ||
log.Println("------------------------------") | ||
log.Printf("Trying connecting to %s (%s), ID=%d\n", endpoints[i].Name, endpoints[i].PublicURL, endpoints[i].ID) | ||
endpoints[i].Containers, err = p.GetDockerContainers(endpoints[i].ID) | ||
if err != nil { | ||
log.Println(string(ColorRed), err, string(ColorReset)) | ||
} | ||
for j := range endpoints[i].Containers { | ||
version := strings.Split(endpoints[i].Containers[j].Image, ":") | ||
if endpoints[i].Containers[j].State == "running" { | ||
log.Printf("factomd container is %s\n%s\n%s\n", endpoints[i].Containers[j].State, endpoints[i].Containers[j].ID, version[1]) | ||
} else { | ||
log.Printf("factomd container is %s\n%s\n%s\n", endpoints[i].Containers[j].State, endpoints[i].Containers[j].ID, version[1]) | ||
} | ||
} | ||
} | ||
} | ||
|
||
// RESTART START | ||
log.Println("------------------------------") | ||
if live { | ||
log.Println("RESTARTING NOW") | ||
} else { | ||
log.Println("SIMULATING RESTART (DRY-RUN)") | ||
} | ||
|
||
var wg sync.WaitGroup | ||
|
||
// Restart each factomd container | ||
for _, e := range endpoints { | ||
if e.PublicURL != "" { | ||
|
||
if len(e.Containers) > 0 { | ||
// for all online hosts with containers, restart factomd container(s) | ||
for _, c := range e.Containers { | ||
if live { | ||
// if live mode, async restarting | ||
wg.Add(1) | ||
go func(name string, endpointID int, containerID string) { | ||
restart(p, name, endpointID, containerID) | ||
wg.Done() | ||
}(e.Name, e.ID, c.ID) | ||
} else { | ||
// if dry-run mode, just print endpoint and containerId | ||
log.Printf("OK %s (%s)\n", e.Name, c.ID) | ||
} | ||
} | ||
} else { | ||
// log skipped endpoints with no containers | ||
log.Printf("SKIP %s", e.Name) | ||
} | ||
|
||
} | ||
} | ||
|
||
wg.Wait() | ||
|
||
} | ||
|
||
func restart(p *Portainer, name string, endpointID int, containerID string) { | ||
|
||
err := p.RestartDockerContainer(endpointID, containerID) | ||
if err != nil { | ||
// if restart request failed, print error | ||
log.Printf("ERROR %s (%s)\n", name, containerID) | ||
log.Println(string(ColorRed), err, string(ColorReset)) | ||
} else { | ||
// no error = success restart, print OK | ||
log.Printf("OK %s (%s)\n", name, containerID) | ||
} | ||
|
||
} |
Oops, something went wrong.