Skip to content

Commit

Permalink
load default variables from the plugin metadata #669
Browse files Browse the repository at this point in the history
  • Loading branch information
matryer committed Mar 29, 2021
1 parent 58d355d commit 5544151
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 33 deletions.
31 changes: 1 addition & 30 deletions pkg/plugins/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package plugins
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
Expand Down Expand Up @@ -181,7 +180,7 @@ func NewPlugin(command string) *Plugin {
// Use the context for cancelation.
func (p *Plugin) Run(ctx context.Context) {
var err error
p.Variables, err = p.loadVariablesFromJSONFile()
p.Variables, err = p.loadVariablesAsEnvVars()
if err != nil {
p.Debugf("ERR: %s", err)
p.OnErr(err)
Expand Down Expand Up @@ -316,34 +315,6 @@ func (p *Plugin) refresh(ctx context.Context) error {
return nil
}

func (p *Plugin) loadVariablesFromJSONFile() ([]string, error) {
variablesJSONFilename := p.Command + variableJSONFileExt
f, err := os.Open(variablesJSONFilename)
if err != nil && os.IsNotExist(err) {
// no .vars.json file - no probs
p.Debugf("(skipping) no variable file: %s", variablesJSONFilename)
return nil, nil
} else if err != nil {
p.Debugf("ERR: %s", variablesJSONFilename, err)
p.OnErr(err)
}
defer f.Close()
b, err := io.ReadAll(io.LimitReader(f, 1_000_000))
if err != nil {
return nil, err
}
p.Debugf("%s: %s", variablesJSONFilename, string(b))
var varmap map[string]interface{}
if err := json.Unmarshal(b, &varmap); err != nil {
return nil, errors.Wrap(err, "json.Unmarshal")
}
var vars []string
for k, v := range varmap {
vars = append(vars, fmt.Sprintf("%s=%v", k, v))
}
return vars, nil
}

// OnErr is called when something has gone wrong at some point.
func (p *Plugin) OnErr(err error) {
p.Items.CycleItems = []*Item{
Expand Down
6 changes: 6 additions & 0 deletions pkg/plugins/testdata/vars-test/plugin.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#!/bin/bash

# <xbar.var>string(XBAR_TEST_EXPLICIT_VAR): An explicit variable</xbar.var>
# <xbar.var>string(XBAR_TEST_DEFAULT_VAR="default-value"): A default variable (from metadata)</xbar.var>
# <xbar.var>string(XBAR_TEST_SET_IN_VARS_JSON): A variable set in the JSON</xbar.var>

echo "XBAR_TEST_EXPLICIT_VAR=${XBAR_TEST_EXPLICIT_VAR}"
echo "XBAR_TEST_SET_IN_VARS_JSON=${XBAR_TEST_SET_IN_VARS_JSON}"
echo "XBAR_TEST_DEFAULT_VAR=${XBAR_TEST_DEFAULT_VAR}"
93 changes: 93 additions & 0 deletions pkg/plugins/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package plugins

import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"sync"

"github.com/matryer/xbar/pkg/metadata"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -50,3 +53,93 @@ func LoadVariableValues(pluginDir, installedPluginPath string) (map[string]inter
}
return values, nil
}

func (p *Plugin) loadVariablesAsEnvVars() ([]string, error) {
vars, err := p.loadVariables()
if err != nil {
return nil, errors.Wrap(err, "loadVariables")
}
envvars := make([]string, 0, len(vars))
for k, v := range vars {
envvars = append(envvars, fmt.Sprintf("%s=%v", k, v))
}
return envvars, nil
}

func (p *Plugin) loadVariables() (map[string]interface{}, error) {
var wg sync.WaitGroup
var defaultVars, jsonFileVars map[string]interface{}
var defaultVarsErr, jsonFileVarsErr error
wg.Add(1)
go func() {
defaultVars, defaultVarsErr = p.loadVariablesFromPluginMetadata()
wg.Done()
}()
wg.Add(1)
go func() {
jsonFileVars, jsonFileVarsErr = p.loadVariablesFromJSONFile()
wg.Done()
}()
wg.Wait()
if defaultVarsErr != nil {
return nil, errors.Wrap(defaultVarsErr, "load default vars")
}
if jsonFileVarsErr != nil {
return nil, errors.Wrap(jsonFileVarsErr, "load json file vars")
}
// add the json file vars to the defaults,
// and return them.
for k, v := range jsonFileVars {
defaultVars[k] = v
}
return defaultVars, nil
}

// loadVariablesFromJSONFile gets a list of environment variable friendly
// key=value pairs.
func (p *Plugin) loadVariablesFromJSONFile() (map[string]interface{}, error) {
variablesJSONFilename := p.Command + variableJSONFileExt
f, err := os.Open(variablesJSONFilename)
if err != nil && os.IsNotExist(err) {
// no .vars.json file - no probs
return nil, nil
} else if err != nil {
return nil, errors.Wrap(err, "open vars json file")
}
defer f.Close()
b, err := io.ReadAll(io.LimitReader(f, 1_000_000))
if err != nil {
return nil, err
}
var vars map[string]interface{}
if err := json.Unmarshal(b, &vars); err != nil {
return nil, errors.Wrap(err, "json.Unmarshal")
}
return vars, nil
}

func (p *Plugin) loadVariablesFromPluginMetadata() (map[string]interface{}, error) {
// read the plugin metadata for default values
pluginFile, err := os.Open(p.Command)
if err != nil {
return nil, errors.Wrap(err, "open plugin source")
}
defer pluginFile.Close()
pluginFileB, err := io.ReadAll(io.LimitReader(pluginFile, 1_000_000))
if err != nil {
return nil, errors.Wrap(err, "read plugin source")
}
pluginMetadata, err := metadata.Parse(metadata.DebugFunc(p.Debugf), p.CleanFilename(), string(pluginFileB))
if err != nil {
return nil, errors.Wrap(err, "metadata.Parse")
}
vars := make(map[string]interface{})
for _, pluginVar := range pluginMetadata.Vars {
if pluginVar.Default == "" {
// skip values with no default
continue
}
vars[pluginVar.Name] = pluginVar.DefaultValue()
}
return vars, nil
}
7 changes: 4 additions & 3 deletions pkg/plugins/variables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ func TestEnvironmentVariables(t *testing.T) {
}
p.Run(ctx)

is.Equal(len(p.Items.CycleItems), 2)
is.Equal(p.Items.CycleItems[0].Text, `XBAR_TEST_EXPLICIT_VAR=explicit`) // inherited
is.Equal(p.Items.CycleItems[1].Text, `XBAR_TEST_SET_IN_VARS_JSON=json`) // in vars.json file
is.Equal(len(p.Items.CycleItems), 3)
is.Equal(p.Items.CycleItems[0].Text, `XBAR_TEST_EXPLICIT_VAR=explicit`) // inherited
is.Equal(p.Items.CycleItems[1].Text, `XBAR_TEST_SET_IN_VARS_JSON=json`) // in vars.json file
is.Equal(p.Items.CycleItems[2].Text, `XBAR_TEST_DEFAULT_VAR=default-value`) // from plugin metadata

}

Expand Down

1 comment on commit 5544151

@Joshfindit
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

Please sign in to comment.