Skip to content

Commit

Permalink
[powercycle] Switch from YAML to JSON5
Browse files Browse the repository at this point in the history
Bug: skia:6933
Change-Id: Ief8680d64fdfe031eceeebea9c117144de1abac4
Reviewed-on: https://skia-review.googlesource.com/32380
Commit-Queue: Stephan Altmueller <[email protected]>
Reviewed-by: Kevin Lubick <[email protected]>
  • Loading branch information
Stephan Altmueller authored and Skia Commit-Bot committed Aug 10, 2017
1 parent 2c7feb4 commit cd7e86f
Show file tree
Hide file tree
Showing 19 changed files with 250 additions and 169 deletions.
2 changes: 1 addition & 1 deletion power/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ The easiest way to test locally is to set up an SSH tunnel to skia-prom

Then, start the server,

go run ./go/power-controller/main.go --logtostderr --alerts_endpoint localhost:8001 --local --powercycle_config ../skolo/sys/powercycle.yaml
go run ./go/power-controller/main.go --logtostderr --alerts_endpoint localhost:8001 --local --powercycle_config ../skolo/sys/powercycle.json5
8 changes: 4 additions & 4 deletions power/go/decider/decider.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type decider struct {
hostMap map[string]string // maps id -> host
}

var yamlFileMatcher = regexp.MustCompile(".+powercycle-(.+).yaml")
var json5FileMatcher = regexp.MustCompile(".+powercycle-(.+).json5")

// New creates a new Decider based off the powercycle configs. It will assume that
// only the bots listed in that config file are powercycleable.
Expand All @@ -38,15 +38,15 @@ func New(powercycleConfigFiles []string) (Decider, map[string]string, error) {
hm := map[string]string{}
ids := util.StringSet{}
for _, file := range powercycleConfigFiles {
dg, err := powercycle.DeviceGroupFromYamlFile(file, false)
dg, err := powercycle.DeviceGroupFromJson5File(file, false)
if err != nil {
return nil, nil, err
}
ids = ids.AddLists(dg.DeviceIDs())
// Extract the jumphost name from the file name of the powercycle config file that
// was passed in.
if matches := yamlFileMatcher.FindStringSubmatch(file); matches == nil {
sklog.Warningf("The powercycle config files are expected to start with a powercycle- prefix and end in .yaml. %s does not", file)
if matches := json5FileMatcher.FindStringSubmatch(file); matches == nil {
sklog.Warningf("The powercycle config files are expected to start with a powercycle- prefix and end in .json5. %s does not", file)
} else {
hostname := "jumphost-" + matches[1]
for _, d := range dg.DeviceIDs() {
Expand Down
2 changes: 1 addition & 1 deletion power/go/power-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ var (
authWhiteList = flag.String("auth_whitelist", login.DEFAULT_DOMAIN_WHITELIST, "White space separated list of domains and email addresses that are allowed to login.")
redirectURL = flag.String("redirect_url", "https://power.skia.org/oauth2callback/", "OAuth2 redirect url. Only used when local=false.")

powercycleConfigs = common.NewMultiStringFlag("powercycle_config", nil, "YAML file with powercycle bot/device configuration. Same as used for powercycle.")
powercycleConfigs = common.NewMultiStringFlag("powercycle_config", nil, "JSON5 file with powercycle bot/device configuration. Same as used for powercycle.")
updatePeriod = flag.Duration("update_period", time.Minute, "How often to update the list of down bots.")
)

Expand Down
4 changes: 2 additions & 2 deletions power/power_release
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ ${INSTALL} --mode=644 -T ./res/img/favicon.ico ${ROOT}/usr/
${INSTALL} --mode=644 -T ./res/js/core.js ${ROOT}/usr/local/share/${APPNAME}/res/js/core.js
${INSTALL} --mode=644 -T ./res/vul/elements.html ${ROOT}/usr/local/share/${APPNAME}/res/vul/elements.html
${INSTALL_DIR} --mode=755 ${ROOT}/etc/powercycle/
${INSTALL} --mode=644 -T ../skolo/sys/powercycle-rpi-01.yaml ${ROOT}/etc/powercycle/powercycle-rpi-01.yaml
${INSTALL} --mode=644 -T ../skolo/sys/powercycle-linux-01.yaml ${ROOT}/etc/powercycle/powercycle-linux-01.yaml
${INSTALL} --mode=644 -T ../skolo/sys/powercycle-rpi-01.json5 ${ROOT}/etc/powercycle/powercycle-rpi-01.json5
${INSTALL} --mode=644 -T ../skolo/sys/powercycle-linux-01.json5 ${ROOT}/etc/powercycle/powercycle-linux-01.json5
}

source ../bash/release.sh
4 changes: 2 additions & 2 deletions power/sys/power-controller.service
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ After=network-online.target
ExecStart=/usr/local/bin/power-controller \
--logtostderr \
--resources_dir=/usr/local/share/power-controller/ \
--powercycle_config=/etc/powercycle/powercycle-rpi-01.yaml \
--powercycle_config=/etc/powercycle/powercycle-linux-01.yaml \
--powercycle_config=/etc/powercycle/powercycle-rpi-01.json5 \
--powercycle_config=/etc/powercycle/powercycle-linux-01.json5 \
--port=:8002
Restart=always
User=default
Expand Down
2 changes: 1 addition & 1 deletion skolo/build_release_powercycle
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ for INSTANCE_ID in $TARGET_INSTANCE_IDS; do

# Install the powercycle binary and config files.
${INSTALL} --mode=755 -T ${GOPATH}/bin/powercycle-cli ${ROOT}/usr/local/bin/powercycle
${INSTALL} --mode=644 -T ./sys/powercycle-${INSTANCE_ID}.yaml ${ROOT}/etc/powercycle.yaml
${INSTALL} --mode=644 -T ./sys/powercycle-${INSTANCE_ID}.json5 ${ROOT}/etc/powercycle.json5
}

source ../bash/release.sh
Expand Down
4 changes: 2 additions & 2 deletions skolo/go/powercycle-cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const (
)

var (
configFile = flag.String("conf", "/etc/powercycle.yaml", "YAML file with device configuration.")
configFile = flag.String("conf", "/etc/powercycle.json5", "JSON5 file with device configuration.")
delay = flag.Int("delay", 0, "Any value > 0 overrides the default duration (in sec) between turning the port off and on.")
connect = flag.Bool("connect", false, "Connect to all the powercycle hosts and verify they are attached computing attached devices.")
list = flag.Bool("l", false, "List the available devices and exit.")
Expand All @@ -40,7 +40,7 @@ func main() {
// powercycle without connecting first, the DeviceGroups won't be properly initialized.
*connect = true
}
devGroup, err := powercycle.DeviceGroupFromYamlFile(*configFile, *connect)
devGroup, err := powercycle.DeviceGroupFromJson5File(*configFile, *connect)
if err != nil {
sklog.Fatalf("Unable to parse config file. Got error: %s", err)
}
Expand Down
4 changes: 2 additions & 2 deletions skolo/go/powercycle/arduino_serial.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import (
// and control an Arduino with servos via the serial_relay program, that
// is assumed to run on the remote host.
type ArduinoConfig struct {
Address string `yaml:"address"` // IP address and port of the device, i.e. 192.168.1.33:22
DevPortMap map[string]int `yaml:"ports"` // Mapping between device name and port on the power strip.
Address string `json:"address"` // IP address and port of the device, i.e. 192.168.1.33:22
DevPortMap map[string]int `json:"ports"` // Mapping between device name and port on the power strip.
}

// ArduinoClient implements the DeviceGroup interface.
Expand Down
4 changes: 2 additions & 2 deletions skolo/go/powercycle/edgeswitch.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ const (
// EdgeSwitchConfig contains configuration options for a single EdgeSwitch.
// Note: We assume the device is on a trusted network.
type EdgeSwitchConfig struct {
Address string `yaml:"address"` // IP address and port of the device, i.e. 192.168.1.33:22
DevPortMap map[string]int `yaml:"ports"` // Mapping between device name and port on the power strip.
Address string `json:"address"` // IP address and port of the device, i.e. 192.168.1.33:22
DevPortMap map[string]int `json:"ports"` // Mapping between device name and port on the power strip.
}

// EdgeSwitchClient allows to control a single EdgeSwitch and
Expand Down
58 changes: 58 additions & 0 deletions skolo/go/powercycle/example.json5
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"mpower": {
"mpower.01": {
"address": "192.168.2.212:22",
"user": "ubnt",
"ports": {
"skia-e-linux-001": 1,
"skia-e-linux-002": 2,
"skia-e-linux-003": 3,
"skia-e-linux-004": 4,
"test-relay-1": 5
}
},
"mpower.02": {
"address": "192.168.2.212:23",
"user": "ubnt",
"ports": {
"skia-e-linux-010": 1,
"skia-e-linux-011": 2,
"skia-e-linux-012": 3,
"skia-e-linux-013": 4,
"test-relay-2": 5
}
}
},
"edgeswitch": {
"edgeswitch.01": {
"address": "192.168.1.41:22",
"ports": {
"skia-rpi-TEST": 23,
"skia-i-rpi-096": 2,
"skia-i-rpi-097": 3,
"skia-i-rpi-098": 4,
"skia-i-rpi-099": 5
}
},
"edgeswitch.02": {
"address": "192.168.1.41:23",
"ports": {
"skia-rpi-2-TEST": 23,
"skia-i-rpi-196": 2,
"skia-i-rpi-197": 3,
"skia-i-rpi-198": 4,
"skia-i-rpi-199": 5
}
},
"edgeswitch.03": {
"address": "192.168.1.41:24",
"ports": {
"skia-rpi-1-TEST": 23,
"skia-i-rpi-296": 2,
"skia-i-rpi-297": 3,
"skia-i-rpi-298": 4,
"skia-i-rpi-299": 5
}
}
}
}
49 changes: 0 additions & 49 deletions skolo/go/powercycle/example.yaml

This file was deleted.

6 changes: 3 additions & 3 deletions skolo/go/powercycle/mpower.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import (
// MPowerConfig contains the necessary parameters to connect
// and control an mPowerPro power strip.
type MPowerConfig struct {
Address string `yaml:"address"` // IP address and port of the device, i.e. 192.168.1.33:22
User string `yaml:"user"` // User of the ssh connection
DevPortMap map[string]int `yaml:"ports"` // Mapping between device name and port on the power strip.
Address string `json:"address"` // IP address and port of the device, i.e. 192.168.1.33:22
User string `json:"user"` // User of the ssh connection
DevPortMap map[string]int `json:"ports"` // Mapping between device name and port on the power strip.
}

// Constants used to access the Ubiquiti mPower Pro.
Expand Down
47 changes: 29 additions & 18 deletions skolo/go/powercycle/powercycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
"sort"
"time"

yaml "gopkg.in/yaml.v2"
"github.com/flynn/json5"

"go.skia.org/infra/go/sklog"
"go.skia.org/infra/go/util"
)

// DeviceGroup describes a set of devices that can all be
Expand Down Expand Up @@ -51,16 +52,16 @@ type PowerStat struct {
// for different device types.
type Config struct {
// MPower aggregates all mPower configurations.
MPower map[string]*MPowerConfig `yaml:"mpower"`
MPower map[string]*MPowerConfig `json:"mpower"`

// EdgeSwitch aggregates all EdgeSwitch configurations.
EdgeSwitch map[string]*EdgeSwitchConfig `yaml:"edgeswitch"`
EdgeSwitch map[string]*EdgeSwitchConfig `json:"edgeswitch"`

// Arduino aggregates all Arduino configurations.
Arduino map[string]*ArduinoConfig `yaml:"arduino"`
Arduino map[string]*ArduinoConfig `json:"arduino"`

// Seeeduino aggregates all Seeeduino configurations.
Seeeduino map[string]*SeeeduinoConfig `yaml:"seeeduino"`
Seeeduino map[string]*SeeeduinoConfig `json:"seeeduino"`
}

// aggregatedDevGroup implements the DeviceGroup interface and allows
Expand Down Expand Up @@ -117,24 +118,14 @@ func (a *aggregatedDevGroup) PowerUsage() (*GroupPowerUsage, error) {
return ret, nil
}

// DeviceGroupFromYamlFile parses a TOML file and instantiates the
// DeviceGroupFromJson5File parses a Json5 file and instantiates the
// defined devices.
func DeviceGroupFromYamlFile(path string, connect bool) (DeviceGroup, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}

yamlBytes, err := ioutil.ReadAll(f)
func DeviceGroupFromJson5File(path string, connect bool) (DeviceGroup, error) {
conf, err := readConfig(path)
if err != nil {
return nil, err
}

conf := &Config{}
if err := yaml.Unmarshal(yamlBytes, conf); err != nil {
return nil, err
}

ret := &aggregatedDevGroup{
idDevGroupMap: map[string]DeviceGroup{},
}
Expand Down Expand Up @@ -187,3 +178,23 @@ func DeviceGroupFromYamlFile(path string, connect bool) (DeviceGroup, error) {

return ret, nil
}

func readConfig(path string) (*Config, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer util.Close(f)

jsonBytes, err := ioutil.ReadAll(f)
if err != nil {
return nil, err
}

conf := &Config{}
if err := json5.Unmarshal(jsonBytes, conf); err != nil {
return nil, err
}

return conf, nil
}
44 changes: 44 additions & 0 deletions skolo/go/powercycle/powercycle_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package powercycle

import (
"testing"

"go.skia.org/infra/go/testutils"

assert "github.com/stretchr/testify/require"
)

var deviceIDs = []string{}

func TestConfig(t *testing.T) {
testutils.MediumTest(t)

dev, err := DeviceGroupFromJson5File("./example.json5", false)
assert.NoError(t, err)
assert.Equal(t, 25, len(dev.DeviceIDs()))

conf, err := readConfig("./example.json5")
assert.NoError(t, err)

for _, oneConf := range conf.Arduino {
assert.NotEqual(t, "", oneConf.Address)
assert.NotEqual(t, 0, len(oneConf.DevPortMap))
}

for _, oneConf := range conf.EdgeSwitch {
assert.NotEqual(t, "", oneConf.Address)
assert.NotEqual(t, 0, len(oneConf.DevPortMap))
}

for _, oneConf := range conf.MPower {
assert.NotEqual(t, "", oneConf.Address)
assert.NotEqual(t, 0, len(oneConf.DevPortMap))
assert.NotEqual(t, "", oneConf.User)
}

for _, oneConf := range conf.Seeeduino {
assert.NotEqual(t, "", oneConf.Address)
assert.NotEqual(t, "", oneConf.BaseURL)
assert.NotEqual(t, 0, len(oneConf.DevPortMap))
}
}
6 changes: 3 additions & 3 deletions skolo/go/powercycle/seeeduino.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import (
// and control an Arduino with servos via the serial_relay program, that
// is assumed to run on the remote host.
type SeeeduinoConfig struct {
Address string `yaml:"address"` // IP address of the device, i.e. 192.168.1.33
BaseURL string `yaml:"base_url"` // Base url that signals a reboot "/arduino/reboot/"
DevPortMap map[string]int `yaml:"ports"` // Mapping between device name and port
Address string `json:"address"` // IP address of the device, i.e. 192.168.1.33
BaseURL string `json:"base_url"` // Base url that signals a reboot "/arduino/reboot/"
DevPortMap map[string]int `json:"ports"` // Mapping between device name and port
}

// SeeeduinoClient implements the DeviceGroup interface.
Expand Down
Loading

0 comments on commit cd7e86f

Please sign in to comment.