Skip to content

Commit

Permalink
Merge pull request #18 from jaypipes/no-retry-fail
Browse files Browse the repository at this point in the history
ensure no retry for create/apply/delete
  • Loading branch information
jaypipes authored Jun 25, 2024
2 parents 3e24bea + f198f96 commit cbcef29
Show file tree
Hide file tree
Showing 15 changed files with 263 additions and 235 deletions.
16 changes: 8 additions & 8 deletions action.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (
"os"
"strings"

"github.com/gdt-dev/gdt/api"
"github.com/gdt-dev/gdt/debug"
gdterrors "github.com/gdt-dev/gdt/errors"
"github.com/gdt-dev/gdt/parse"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
Expand Down Expand Up @@ -226,7 +226,7 @@ func (a *Action) create(
if err != nil {
// This should never happen because we check during parse time
// whether the file can be opened.
rterr := fmt.Errorf("%w: %s", gdterrors.RuntimeError, err)
rterr := fmt.Errorf("%w: %s", api.RuntimeError, err)
return rterr
}
defer f.Close()
Expand All @@ -245,7 +245,7 @@ func (a *Action) create(

objs, err := unstructuredFromReader(r)
if err != nil {
rterr := fmt.Errorf("%w: %s", gdterrors.RuntimeError, err)
rterr := fmt.Errorf("%w: %s", api.RuntimeError, err)
return rterr
}
for _, obj := range objs {
Expand Down Expand Up @@ -290,7 +290,7 @@ func (a *Action) apply(
if err != nil {
// This should never happen because we check during parse time
// whether the file can be opened.
rterr := fmt.Errorf("%w: %s", gdterrors.RuntimeError, err)
rterr := fmt.Errorf("%w: %s", api.RuntimeError, err)
return rterr
}
defer f.Close()
Expand All @@ -309,7 +309,7 @@ func (a *Action) apply(

objs, err := unstructuredFromReader(r)
if err != nil {
rterr := fmt.Errorf("%w: %s", gdterrors.RuntimeError, err)
rterr := fmt.Errorf("%w: %s", api.RuntimeError, err)
return rterr
}
for _, obj := range objs {
Expand Down Expand Up @@ -358,13 +358,13 @@ func (a *Action) delete(
if err != nil {
// This should never happen because we check during parse time
// whether the file can be opened.
rterr := fmt.Errorf("%w: %s", gdterrors.RuntimeError, err)
rterr := fmt.Errorf("%w: %s", api.RuntimeError, err)
return rterr
}
defer f.Close()
objs, err := unstructuredFromReader(f)
if err != nil {
rterr := fmt.Errorf("%w: %s", gdterrors.RuntimeError, err)
rterr := fmt.Errorf("%w: %s", api.RuntimeError, err)
return rterr
}
for _, obj := range objs {
Expand All @@ -378,7 +378,7 @@ func (a *Action) delete(
if ons == "" {
ons = ns
}
if err = a.doDelete(ctx, c, res, name, ns); err != nil {
if err = a.doDelete(ctx, c, res, name, ons); err != nil {
return err
}
}
Expand Down
59 changes: 14 additions & 45 deletions assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ import (
"net/http"
"strings"

"github.com/gdt-dev/gdt/api"
gdtjson "github.com/gdt-dev/gdt/assertion/json"
gdterrors "github.com/gdt-dev/gdt/errors"
gdttypes "github.com/gdt-dev/gdt/types"
"gopkg.in/yaml.v3"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
Expand Down Expand Up @@ -166,8 +165,8 @@ type Expect struct {
// conditionMatch is a struct with fields that we will match a resource's
// `Condition` against.
type conditionMatch struct {
Status *gdttypes.FlexStrings `yaml:"status,omitempty"`
Reason string `yaml:"reason,omitempty"`
Status *api.FlexStrings `yaml:"status,omitempty"`
Reason string `yaml:"reason,omitempty"`
}

// ConditionMatch can be a string (the ConditionStatus to match), a slice of
Expand All @@ -182,7 +181,7 @@ type ConditionMatch struct {
// ConditionMatch can be either a string, a slice of strings, or an object with .
func (m *ConditionMatch) UnmarshalYAML(node *yaml.Node) error {
if node.Kind == yaml.ScalarNode || node.Kind == yaml.SequenceNode {
var fs gdttypes.FlexStrings
var fs api.FlexStrings
if err := node.Decode(&fs); err != nil {
return ConditionMatchInvalid(node, err)
}
Expand All @@ -203,10 +202,10 @@ func (m *ConditionMatch) UnmarshalYAML(node *yaml.Node) error {
type PlacementAssertion struct {
// Spread contains zero or more topology keys that gdt-kube will assert an
// even spread across.
Spread *gdttypes.FlexStrings `yaml:"spread,omitempty"`
Spread *api.FlexStrings `yaml:"spread,omitempty"`
// Pack contains zero or more topology keys that gdt-kube will assert
// bin-packing of resources within.
Pack *gdttypes.FlexStrings `yaml:"pack,omitempty"`
Pack *api.FlexStrings `yaml:"pack,omitempty"`
}

// assertions contains all assertions made for the exec test
Expand Down Expand Up @@ -246,7 +245,7 @@ func (a *assertions) OK(ctx context.Context) bool {
exp := a.exp
if exp == nil {
if a.err != nil {
a.Fail(gdterrors.UnexpectedError(a.err))
a.Fail(api.UnexpectedError(a.err))
return false
}
return true
Expand Down Expand Up @@ -309,16 +308,16 @@ func (a *assertions) errorOK() bool {
}
if exp.Error != "" && a.r != nil {
if a.err == nil {
a.Fail(gdterrors.UnexpectedError(a.err))
a.Fail(api.UnexpectedError(a.err))
return false
}
if !strings.Contains(a.err.Error(), exp.Error) {
a.Fail(gdterrors.NotIn(a.err.Error(), exp.Error))
a.Fail(api.NotIn(a.err.Error(), exp.Error))
return false
}
}
if a.err != nil {
a.Fail(gdterrors.UnexpectedError(a.err))
a.Fail(api.UnexpectedError(a.err))
return false
}
return true
Expand All @@ -329,36 +328,6 @@ func (a *assertions) expectsNotFound() bool {
return (exp.Len != nil && *exp.Len == 0) || exp.NotFound
}

// notFoundOK returns true if the supplied error and response matches the
// NotFound condition and the Len==0 condition, false otherwise
func (a *assertions) notFoundOK() bool {
if a.expectsNotFound() {
// First check if the error is like one returned from Get or Delete
// that has a 404 ErrStatus.Code in it
apierr, ok := a.err.(*apierrors.StatusError)
if ok {
if http.StatusNotFound != int(apierr.ErrStatus.Code) {
msg := fmt.Sprintf("got status code %d", apierr.ErrStatus.Code)
a.Fail(ExpectedNotFound(msg))
return false
}
return true
}
// Next check to see if the supplied resp is a list of objects returned
// by the dynamic client and if so, is that an empty list.
list, ok := a.r.(*unstructured.UnstructuredList)
if ok {
if len(list.Items) != 0 {
msg := fmt.Sprintf("got %d items", len(list.Items))
a.Fail(ExpectedNotFound(msg))
return false
}
return true
}
}
return true
}

// lenOK returns true if the subject matches the Len condition, false otherwise
func (a *assertions) lenOK() bool {
exp := a.exp
Expand All @@ -368,7 +337,7 @@ func (a *assertions) lenOK() bool {
list, ok := a.r.(*unstructured.UnstructuredList)
if ok && list != nil {
if len(list.Items) != *exp.Len {
a.Fail(gdterrors.NotEqualLength(*exp.Len, len(list.Items)))
a.Fail(api.NotEqualLength(*exp.Len, len(list.Items)))
return false
}
}
Expand Down Expand Up @@ -402,7 +371,7 @@ func (a *assertions) matchesOK() bool {
// for _, obj := range list.Items {
// diff := compareResourceToMatchObject(obj, matchObj)
//
// a.Fail(gdterrors.NotEqualLength(*exp.Len, len(list.Items)))
// a.Fail(api.NotEqualLength(*exp.Len, len(list.Items)))
// return false
// }
//}
Expand Down Expand Up @@ -435,7 +404,7 @@ func (a *assertions) conditionsOK() bool {
// for _, obj := range list.Items {
// diff := compareResourceToMatchObject(obj, matchObj)
//
// a.Fail(gdterrors.NotEqualLength(*exp.Len, len(list.Items)))
// a.Fail(api.NotEqualLength(*exp.Len, len(list.Items)))
// return false
// }
//}
Expand Down Expand Up @@ -511,7 +480,7 @@ func newAssertions(
exp *Expect,
err error,
r interface{},
) gdttypes.Assertions {
) api.Assertions {
return &assertions{
c: c,
failures: []error{},
Expand Down
44 changes: 21 additions & 23 deletions compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package kube

import (
"fmt"
"io/ioutil"
"os"
"reflect"
"strconv"
"strings"
Expand Down Expand Up @@ -42,7 +42,7 @@ func compareConditions(
panic(msg)
}
if (!found || len(conds) == 0) && len(expected) != 0 {
for condType, _ := range expected {
for condType := range expected {
d.Add(fmt.Sprintf("no condition with type %q found", condType))
}
return d
Expand Down Expand Up @@ -130,13 +130,13 @@ func compareConditions(
// map[string]interface{} is the collection of resource fields that we will
// match against.
func matchObjectFromAny(m interface{}) map[string]interface{} {
switch m.(type) {
switch m := m.(type) {
case string:
var err error
var b []byte
v := m.(string)
v := m
if probablyFilePath(v) {
b, err = ioutil.ReadFile(v)
b, err = os.ReadFile(v)
if err != nil {
// NOTE(jaypipes): We already validated that the file exists at
// parse time. If we get an error here, just panic cuz there's
Expand All @@ -155,7 +155,7 @@ func matchObjectFromAny(m interface{}) map[string]interface{} {
}
return obj
case map[string]interface{}:
return m.(map[string]interface{})
return m
}
return map[string]interface{}{}
}
Expand Down Expand Up @@ -238,7 +238,7 @@ func collectFieldDifferences(
}
return
case int, int8, int16, int32, int64:
switch subject.(type) {
switch subject := subject.(type) {
case int, int8, int16, int32, int64:
mv := toInt64(match)
sv := toInt64(subject)
Expand All @@ -261,8 +261,7 @@ func collectFieldDifferences(
}
case string:
mv := toInt64(match)
ss := subject.(string)
sv, err := strconv.Atoi(ss)
sv, err := strconv.Atoi(subject)
if err != nil {
diff := fmt.Sprintf(
"%s had different values. expected %v but found %v",
Expand Down Expand Up @@ -296,8 +295,7 @@ func collectFieldDifferences(
}
case string:
mv, _ := match.(string)
sv, _ := subject.(string)
if mv != sv {
if mv != subject {
diff := fmt.Sprintf(
"%s had different values. expected %v but found %v",
fp, match, subject,
Expand Down Expand Up @@ -362,34 +360,34 @@ func typesComparable(a, b interface{}) bool {

// toUint64 takes an interface and returns a uint64
func toUint64(v interface{}) uint64 {
switch v.(type) {
switch v := v.(type) {
case uint64:
return v.(uint64)
return v
case uint8:
return uint64(v.(uint8))
return uint64(v)
case uint16:
return uint64(v.(uint16))
return uint64(v)
case uint32:
return uint64(v.(uint32))
return uint64(v)
case uint:
return uint64(v.(uint))
return uint64(v)
}
return 0
}

// toInt64 takes an interface and returns an int64
func toInt64(v interface{}) int64 {
switch v.(type) {
switch v := v.(type) {
case int64:
return v.(int64)
return v
case int8:
return int64(v.(int8))
return int64(v)
case int16:
return int64(v.(int16))
return int64(v)
case int32:
return int64(v.(int32))
return int64(v)
case int:
return int64(v.(int))
return int64(v)
}
return 0
}
11 changes: 5 additions & 6 deletions defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ package kube
import (
"os"

"github.com/gdt-dev/gdt/errors"
gdttypes "github.com/gdt-dev/gdt/types"
"github.com/gdt-dev/gdt/api"
"gopkg.in/yaml.v3"
)

Expand Down Expand Up @@ -39,21 +38,21 @@ type Defaults struct {

func (d *Defaults) UnmarshalYAML(node *yaml.Node) error {
if node.Kind != yaml.MappingNode {
return errors.ExpectedMapAt(node)
return api.ExpectedMapAt(node)
}
// maps/structs are stored in a top-level Node.Content field which is a
// concatenated slice of Node pointers in pairs of key/values.
for i := 0; i < len(node.Content); i += 2 {
keyNode := node.Content[i]
if keyNode.Kind != yaml.ScalarNode {
return errors.ExpectedScalarAt(keyNode)
return api.ExpectedScalarAt(keyNode)
}
key := keyNode.Value
valNode := node.Content[i+1]
switch key {
case "kube":
if valNode.Kind != yaml.MappingNode {
return errors.ExpectedMapAt(valNode)
return api.ExpectedMapAt(valNode)
}
hd := kubeDefaults{}
if err := valNode.Decode(&hd); err != nil {
Expand Down Expand Up @@ -86,7 +85,7 @@ func (d *Defaults) validate() error {
}

// fromBaseDefaults returns an gdt-kube plugin-specific Defaults from a Spec
func fromBaseDefaults(base *gdttypes.Defaults) *Defaults {
func fromBaseDefaults(base *api.Defaults) *Defaults {
if base == nil {
return nil
}
Expand Down
Loading

0 comments on commit cbcef29

Please sign in to comment.