// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package mock import ( "fmt" "math/rand" "sort" "strings" "time" "github.com/brianvoe/gofakeit/v6" "github.com/hashicorp/nomad/nomad/structs" ) type MockVariables map[string]*structs.VariableDecrypted func Variable() *structs.VariableDecrypted { return &structs.VariableDecrypted{ VariableMetadata: mockVariableMetadata(), Items: structs.VariableItems{ "key1": "value1", "key2": "value2", }, } } // Variables returns a random number of variables between min // and max inclusive. func Variables(minU, maxU uint8) MockVariables { // the unsignedness of the args is to prevent goofy parameters, they're // easier to work with as ints in this code. min := int(minU) max := int(maxU) vc := min // handle cases with irrational arguments. Max < Min = min if max > min { vc = rand.Intn(max-min) + min } svs := make([]*structs.VariableDecrypted, vc) paths := make(map[string]*structs.VariableDecrypted, vc) for i := 0; i < vc; i++ { nv := Variable() // There is an extremely rare chance of path collision because the mock // variables generate their paths randomly. This check will add // an extra component on conflict to (ideally) disambiguate them. if _, found := paths[nv.Path]; found { nv.Path = nv.Path + "/" + fmt.Sprint(time.Now().UnixNano()) } paths[nv.Path] = nv svs[i] = nv } return paths } func (svs MockVariables) ListPaths() []string { out := make([]string, 0, len(svs)) for _, sv := range svs { out = append(out, sv.Path) } sort.Strings(out) return out } func (svs MockVariables) List() []*structs.VariableDecrypted { out := make([]*structs.VariableDecrypted, 0, len(svs)) for _, p := range svs.ListPaths() { pc := svs[p].Copy() out = append(out, &pc) } return out } type MockVariablesEncrypted map[string]*structs.VariableEncrypted func VariableEncrypted() *structs.VariableEncrypted { return &structs.VariableEncrypted{ VariableMetadata: mockVariableMetadata(), VariableData: structs.VariableData{ KeyID: "foo", Data: []byte("foo"), }, } } // VariablesEncrypted returns a random number of variables between min // and max inclusive. func VariablesEncrypted(minU, maxU uint8) MockVariablesEncrypted { // the unsignedness of the args is to prevent goofy parameters, they're // easier to work with as ints in this code. min := int(minU) max := int(maxU) vc := min // handle cases with irrational arguments. Max < Min = min if max > min { vc = rand.Intn(max-min) + min } svs := make([]*structs.VariableEncrypted, vc) paths := make(map[string]*structs.VariableEncrypted, vc) for i := 0; i < vc; i++ { nv := VariableEncrypted() // There is an extremely rare chance of path collision because the mock // variables generate their paths randomly. This check will add // an extra component on conflict to (ideally) disambiguate them. if _, found := paths[nv.Path]; found { nv.Path = nv.Path + "/" + fmt.Sprint(time.Now().UnixNano()) } paths[nv.Path] = nv svs[i] = nv } return paths } func (svs MockVariablesEncrypted) ListPaths() []string { out := make([]string, 0, len(svs)) for _, sv := range svs { out = append(out, sv.Path) } sort.Strings(out) return out } func (svs MockVariablesEncrypted) List() []*structs.VariableEncrypted { out := make([]*structs.VariableEncrypted, 0, len(svs)) for _, p := range svs.ListPaths() { pc := svs[p].Copy() out = append(out, &pc) } return out } func mockVariableMetadata() structs.VariableMetadata { envs := []string{"dev", "test", "prod"} envIdx := rand.Intn(3) env := envs[envIdx] domain := gofakeit.DomainName() out := structs.VariableMetadata{ Namespace: "default", Path: strings.ReplaceAll(env+"."+domain, ".", "/"), CreateIndex: uint64(rand.Intn(100) + 100), CreateTime: gofakeit.DateRange(time.Now().AddDate(0, -1, 0), time.Now()).UnixNano(), } out.ModifyIndex = out.CreateIndex out.ModifyTime = out.CreateTime // Flip a coin to see if we should return a "modified" object if gofakeit.Bool() { out.ModifyTime = gofakeit.DateRange(time.Unix(0, out.CreateTime), time.Now()).UnixNano() out.ModifyIndex = out.CreateIndex + uint64(rand.Intn(100)) } return out }