mirror of https://github.com/knative/pkg.git
Add metahelper for reading/writing metadata in Prow (#773)
* Add metahelper for writing metadata in Prow * Update prow package importing path
This commit is contained in:
parent
ea367c1342
commit
f0ffda4667
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
Copyright 2019 The Knative Authors
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Package client supports various needs for running tests
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"knative.dev/pkg/test/prow"
|
||||
)
|
||||
|
||||
const (
|
||||
filename = "metadata.json"
|
||||
)
|
||||
|
||||
// client holds metadata as a string:string map, as well as path for storing
|
||||
// metadata
|
||||
type client struct {
|
||||
MetaData map[string]string
|
||||
Path string
|
||||
}
|
||||
|
||||
// NewClient creates a client, takes custom directory for storing `metadata.json`.
|
||||
// It reads existing `metadata.json` file if it exists, otherwise creates it.
|
||||
// Errors out if there is any file i/o problem other than file not exist error.
|
||||
func NewClient(dir string) (*client, error) {
|
||||
c := &client{
|
||||
MetaData: make(map[string]string),
|
||||
}
|
||||
if dir == "" {
|
||||
log.Println("Getting artifacts dir from prow")
|
||||
dir = prow.GetLocalArtifactsDir()
|
||||
}
|
||||
c.Path = path.Join(dir, filename)
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(dir, 0777); err != nil {
|
||||
return nil, fmt.Errorf("Failed to create directory: %v", err)
|
||||
}
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// sync is shared by Get and Set, invoked at the very beginning of each, makes
|
||||
// sure the file exists, and loads the content of file into c.MetaData
|
||||
func (c *client) sync() error {
|
||||
_, err := os.Stat(c.Path)
|
||||
if os.IsNotExist(err) {
|
||||
body, _ := json.Marshal(&c.MetaData)
|
||||
err = ioutil.WriteFile(c.Path, body, 0777)
|
||||
} else {
|
||||
var body []byte
|
||||
body, err = ioutil.ReadFile(c.Path)
|
||||
if err == nil {
|
||||
err = json.Unmarshal(body, &c.MetaData)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Set sets key:val pair, and overrides if it exists
|
||||
func (c *client) Set(key, val string) error {
|
||||
err := c.sync()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if oldVal, ok := c.MetaData[key]; ok {
|
||||
log.Printf("Overriding meta %q:%q with new value %q", key, oldVal, val)
|
||||
}
|
||||
c.MetaData[key] = val
|
||||
body, _ := json.Marshal(c.MetaData)
|
||||
return ioutil.WriteFile(c.Path, body, 0777)
|
||||
}
|
||||
|
||||
// Get gets val for key
|
||||
func (c *client) Get(key string) (string, error) {
|
||||
if _, err := os.Stat(c.Path); err != nil && os.IsNotExist(err) {
|
||||
return "", fmt.Errorf("file %q doesn't exist", c.Path)
|
||||
}
|
||||
var res string
|
||||
err := c.sync()
|
||||
if err == nil {
|
||||
if val, ok := c.MetaData[key]; ok {
|
||||
res = val
|
||||
} else {
|
||||
err = fmt.Errorf("key %q doesn't exist", key)
|
||||
}
|
||||
}
|
||||
return res, err
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
Copyright 2019 The Knative Authors
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Package client supports various needs for running tests
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
fakeArtifactDir = "fakeArtifactDir"
|
||||
mockArtifactEnv = "mockArtifactDir"
|
||||
)
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
datas := []struct {
|
||||
customDir string
|
||||
expPath string
|
||||
expErr bool
|
||||
}{
|
||||
{ // default dir
|
||||
"", "mockArtifactDir/metadata.json", false,
|
||||
}, { // custom dir
|
||||
"a", "a/metadata.json", false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, data := range datas {
|
||||
dir := data.customDir
|
||||
if data.customDir == "" { // use env var
|
||||
oriArtifactDir := os.Getenv("ARTIFACTS")
|
||||
defer os.Setenv("ARTIFACTS", oriArtifactDir)
|
||||
os.Setenv("ARTIFACTS", mockArtifactEnv)
|
||||
dir = mockArtifactEnv
|
||||
}
|
||||
os.RemoveAll(dir)
|
||||
defer os.RemoveAll(dir)
|
||||
c, err := NewClient(data.customDir)
|
||||
errMsg := fmt.Sprintf("Testing new client with dir: %q", data.customDir)
|
||||
if (err == nil && data.expErr) || (err != nil && !data.expErr) {
|
||||
log.Fatalf("%s\ngot: '%v', want: '%v'", errMsg, err, data.expErr)
|
||||
}
|
||||
if c.Path != data.expPath {
|
||||
log.Fatalf("%s\ngot: %q, want: %q", errMsg, c.Path, data.expPath)
|
||||
}
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
log.Fatalf("%s\nDirectory %q wasn't created", errMsg, dir)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestSync(t *testing.T) {
|
||||
datas := []struct {
|
||||
fileExist bool
|
||||
content string
|
||||
expMetadata map[string]string
|
||||
expErr bool
|
||||
}{
|
||||
{ // file not exist
|
||||
false, "", make(map[string]string), false,
|
||||
}, { // file exist but empty
|
||||
true, "", make(map[string]string), true,
|
||||
}, { // file exist, invalid
|
||||
true, "{", make(map[string]string), true,
|
||||
}, { // file exist valid
|
||||
true, "{}", make(map[string]string), false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, data := range datas {
|
||||
c, _ := NewClient(fakeArtifactDir)
|
||||
os.Remove(c.Path)
|
||||
if data.fileExist {
|
||||
defer os.Remove(c.Path)
|
||||
ioutil.WriteFile(c.Path, []byte(data.content), 0644)
|
||||
}
|
||||
err := c.sync()
|
||||
errMsg := fmt.Sprintf("Testing syncing with file exist: %v, content: %q", data.fileExist, data.content)
|
||||
if (err == nil && data.expErr) || (err != nil && !data.expErr) {
|
||||
log.Fatalf("%s\ngot: '%v', want: '%v'", errMsg, err, data.expErr)
|
||||
}
|
||||
if !reflect.DeepEqual(c.MetaData, data.expMetadata) {
|
||||
log.Fatalf("%s\ngot: '%v', want: '%v'", errMsg, c.MetaData, data.expMetadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSet(t *testing.T) {
|
||||
datas := []struct {
|
||||
metadata map[string]string
|
||||
content string
|
||||
setKey string
|
||||
setVal string
|
||||
expMetadata map[string]string
|
||||
expErr bool
|
||||
}{
|
||||
{ // sync failed
|
||||
make(map[string]string), "", "", "", make(map[string]string), true,
|
||||
}, { // set normal key
|
||||
make(map[string]string), "{}", "a", "b", map[string]string{"a": "b"}, false,
|
||||
}, { // override
|
||||
make(map[string]string), "{\"a\":\"b\"}", "a", "c", map[string]string{"a": "c"}, false,
|
||||
}, { // ignore old client val
|
||||
map[string]string{"a": "b"}, "{}", "c", "d", map[string]string{"c": "d"}, false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, data := range datas {
|
||||
c, _ := NewClient(fakeArtifactDir)
|
||||
defer os.Remove(c.Path)
|
||||
ioutil.WriteFile(c.Path, []byte(data.content), 0644)
|
||||
|
||||
err := c.Set(data.setKey, data.setVal)
|
||||
errMsg := fmt.Sprintf("Testing set %q:%q, with metadata: %v, content: %q",
|
||||
data.setKey, data.setVal, data.metadata, data.content)
|
||||
if (err == nil && data.expErr) || (err != nil && !data.expErr) {
|
||||
log.Fatalf("%s\ngot: '%v', want: '%v'", errMsg, err, data.expErr)
|
||||
}
|
||||
if !reflect.DeepEqual(c.MetaData, data.expMetadata) {
|
||||
log.Fatalf("%s\ngot: '%v', want: '%v'", errMsg, c.MetaData, data.expMetadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
datas := []struct {
|
||||
metadata map[string]string
|
||||
content string
|
||||
getKey string
|
||||
expMetadata map[string]string
|
||||
expVal string
|
||||
expErr bool
|
||||
}{
|
||||
{ // sync failed
|
||||
make(map[string]string), "", "", make(map[string]string), "", true,
|
||||
}, { // get normal key
|
||||
make(map[string]string), "{\"a\":\"b\"}", "a", map[string]string{"a": "b"}, "b", false,
|
||||
}, { // key not exist
|
||||
make(map[string]string), "{\"a\":\"b\"}", "c", map[string]string{"a": "b"}, "", true,
|
||||
}, { // ignore old client val
|
||||
map[string]string{"a": "c"}, "{\"a\":\"b\"}", "a", map[string]string{"a": "b"}, "b", false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, data := range datas {
|
||||
c, _ := NewClient(fakeArtifactDir)
|
||||
defer os.Remove(c.Path)
|
||||
ioutil.WriteFile(c.Path, []byte(data.content), 0644)
|
||||
|
||||
val, err := c.Get(data.getKey)
|
||||
errMsg := fmt.Sprintf("Testing get %q, with metadata: %v, content: %q",
|
||||
data.getKey, data.metadata, data.content)
|
||||
if (err == nil && data.expErr) || (err != nil && !data.expErr) {
|
||||
log.Fatalf("%s\ngot: '%v', want: '%v'", errMsg, err, data.expErr)
|
||||
}
|
||||
if !reflect.DeepEqual(c.MetaData, data.expMetadata) {
|
||||
log.Fatalf("%s\ngot: '%v', want: '%v'", errMsg, c.MetaData, data.expMetadata)
|
||||
}
|
||||
if val != data.expVal {
|
||||
log.Fatalf("%s\ngot: %q, want: %q", errMsg, val, data.expVal)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
Copyright 2019 The Knative Authors
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"knative.dev/pkg/testutils/metahelper/client"
|
||||
)
|
||||
|
||||
var (
|
||||
getKeyOpt string
|
||||
saveKeyOpt string
|
||||
valOpt string
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&getKeyOpt, "get", "", "get val for a key")
|
||||
flag.StringVar(&saveKeyOpt, "set", "", "save val for a key, must have --val supplied")
|
||||
flag.StringVar(&valOpt, "val", "", "val to be modified, only useful when --save is passed")
|
||||
flag.Parse()
|
||||
// Create with default path of metahelper/client, so that the path is
|
||||
// consistent with all other consumers of metahelper/client that run within
|
||||
// the same context of this tool
|
||||
c, err := client.NewClient("")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var res string
|
||||
switch {
|
||||
case getKeyOpt != "" && saveKeyOpt != "":
|
||||
log.Fatal("--get and --save can't be used at the same time")
|
||||
case getKeyOpt != "":
|
||||
gotVal, err := c.Get(getKeyOpt)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed getting value for %q from %q: '%v'", getKeyOpt, c.Path, err)
|
||||
}
|
||||
res = gotVal
|
||||
case saveKeyOpt != "":
|
||||
if valOpt == "" {
|
||||
log.Fatal("--val must be supplied when using --save")
|
||||
}
|
||||
log.Printf("Writing files to %s", c.Path)
|
||||
if err := c.Set(saveKeyOpt, valOpt); err != nil {
|
||||
log.Fatalf("Failed saving %q:%q to %q: '%v'", saveKeyOpt, valOpt, c.Path, err)
|
||||
}
|
||||
}
|
||||
fmt.Print(res)
|
||||
}
|
Loading…
Reference in New Issue