Skip to content

Commit

Permalink
feat: add filter to params
Browse files Browse the repository at this point in the history
  • Loading branch information
nehemming committed Aug 9, 2021
1 parent 2d92878 commit b58d4db
Show file tree
Hide file tree
Showing 8 changed files with 286 additions and 152 deletions.
17 changes: 16 additions & 1 deletion internal/cmd/initconfig.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ params:
# skipExpand: false
# optional: false

# a filter section can be added to params, if the filter excludes the param the entry is ignored.
# The filter can exclude specific operating systems or architectures on which cirocket is running.
# This can be useful if task have windows or linux specific scripts/settings etc.
# Values used for filtering come from the go
# architecture and os names ... i.e. macos is known as darwin.
# filter:
# includeOS:
# - windows
# includeArch:
# - amd64
# excludeOS:
# - linux
# excludeArch:
# - i386

# must section can be supplied on missions, stages or tasks. It checks that the caller of that activity
# has provided the a parameter with the name of the must entry. If it is not provided an error occurs.
# this check can be used to safeguard an activity against bad input config
Expand Down Expand Up @@ -63,7 +78,7 @@ stages:

# a filter section can be added to tasks and stages, this limits the running of the step to
# host applications running on specific operating systems or architectures. This can be useful
# if task have windows or linux specific scripts etc. Values used for filtering come form the go
# if task have windows or linux specific scripts etc. Values used for filtering come from the go
# architecture and os names ... i.e. macos is known as darwin.
# filter:
# includeOS:
Expand Down
4 changes: 3 additions & 1 deletion pkg/rocket/assemble.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,9 @@ func mergeParamSets(sourceParams []Param, additional ...Param) []Param {
params := make([]Param, 0, len(additional))
for _, p := range additional {
if _, ok := m[p.Name]; !ok || p.Name == "" {
params = append(params, p)
if !p.Filter.IsFiltered() {
params = append(params, p)
}
}
}

Expand Down
66 changes: 6 additions & 60 deletions pkg/rocket/capcomm.go
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,11 @@ func (capComm *CapComm) MergeParams(ctx context.Context, params []Param) error {
kvg := capComm.params.(*KeyValueGetter)

for index, p := range params {
// exclude filtered
if p.Filter.IsFiltered() {
continue
}

if p.Name == "" {
return fmt.Errorf("parameter %d has no name", index)
}
Expand All @@ -674,7 +679,7 @@ func (capComm *CapComm) MergeParams(ctx context.Context, params []Param) error {
func (capComm *CapComm) MergeTemplateEnvs(ctx context.Context, env EnvMap) error {
capComm.mustNotBeSealed()

// Params need to be expanded prior to merging
// Envs need to be expanded prior to merging
expanded := make(map[string]string)

for k, p := range env {
Expand Down Expand Up @@ -889,65 +894,6 @@ func (capComm *CapComm) expandParam(ctx context.Context, param Param) (string, e
return value, nil
}

// isFiltered returns true if the filter restricts
// the item from being included.
// False means do not process any further.
func (capComm *CapComm) isFiltered(filter *Filter) bool { //nolint remain as iis for now
if filter == nil {
return false
}

if filter.Skip {
return true
}

if len(filter.ExcludeArch) > 0 {
for _, a := range filter.ExcludeArch {
if a == capComm.runtime.GOARCH {
return true
}
}
}

if len(filter.ExcludeOS) > 0 {
for _, o := range filter.ExcludeOS {
if o == capComm.runtime.GOOS {
return true
}
}
}

if len(filter.IncludeArch) > 0 {
included := false
for _, a := range filter.IncludeArch {
if a == capComm.runtime.GOARCH {
included = true
break
}
}

if !included {
return true
}
}

if len(filter.IncludeOS) > 0 {
included := false
for _, o := range filter.IncludeOS {
if o == capComm.runtime.GOOS {
included = true
break
}
}

if !included {
return true
}
}

return false
}

// mustNotBeSealed asserts that the seal is not in place.
func (capComm *CapComm) mustNotBeSealed() {
if capComm.sealed {
Expand Down
146 changes: 64 additions & 82 deletions pkg/rocket/capcomm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1087,87 +1087,6 @@ func TestGetExecEnv(t *testing.T) {
}
}

func TestIsFilteredInclude(t *testing.T) {
capComm := NewCapComm(testMissionFile, stdlog.New())

if capComm.isFiltered(nil) != false {
t.Error("Nil should not filter")
}

// Included testing
f := &Filter{}
if capComm.isFiltered(f) != false {
t.Error("Empty should not filter")
}
f.IncludeOS = []string{runtime.GOOS}
if capComm.isFiltered(f) != false {
t.Error("Same Os should not filter")
}
f.IncludeArch = []string{runtime.GOARCH}
if capComm.isFiltered(f) != false {
t.Error("Same Arch should not filter")
}
}

func TestIsFilteredNotInclude(t *testing.T) {
capComm := NewCapComm(testMissionFile, stdlog.New())

if capComm.isFiltered(nil) != false {
t.Error("Nil should not filter")
}

// Not included testing
f := &Filter{}
f.IncludeOS = []string{runtime.GOOS + "nope"}
if capComm.isFiltered(f) != true {
t.Error("Diff Os should filter")
}
f.IncludeArch = []string{runtime.GOARCH + "nope"}
if capComm.isFiltered(f) != true {
t.Error("Diff Arch should filter")
}
}

func TestIsFilteredExclude(t *testing.T) {
capComm := NewCapComm(testMissionFile, stdlog.New())

if capComm.isFiltered(nil) != false {
t.Error("Nil should not filter")
}

// Exclude
f := &Filter{}
f.ExcludeOS = []string{runtime.GOOS}
if capComm.isFiltered(f) != true {
t.Error("Same Os should exclude filter")
}
f = &Filter{}
f.ExcludeArch = []string{runtime.GOARCH}
if capComm.isFiltered(f) != true {
t.Error("Same Arch should exclude filter")
}
}

func TestIsFilteredNotExclude(t *testing.T) {
capComm := NewCapComm(testMissionFile, stdlog.New())

if capComm.isFiltered(nil) != false {
t.Error("Nil should not filter")
}

// Non exclude test
f := &Filter{}
f.ExcludeOS = []string{runtime.GOOS + "nope"}
if capComm.isFiltered(f) != false {
t.Error("Diff Os should exclude filter")
}
f = &Filter{}
f.ExcludeArch = []string{runtime.GOARCH + "nope"}
if capComm.isFiltered(f) != false {
t.Error("Diff Arch should exclude filter")
}
}

func TestMustNotBeSealed(t *testing.T) {
defer func() {
if r := recover(); r == nil {
Expand Down Expand Up @@ -1542,7 +1461,7 @@ func TestStringExpandNoValueIssue(t *testing.T) {
}
}

func TestExpandAdjacentMergeParamsWorks(t *testing.T) {
func TestExpandAdjacentMergeParamsExpandsInOrder(t *testing.T) {
ctx := context.Background()
capComm := NewCapComm(testMissionFile, stdlog.New())

Expand Down Expand Up @@ -1570,6 +1489,69 @@ func TestExpandAdjacentMergeParamsWorks(t *testing.T) {
}
}

func TestParamsFilter(t *testing.T) {
ctx := context.Background()
capComm := NewCapComm(testMissionFile, stdlog.New())

params := []Param{
{
Name: "one",
Value: "here",
},
{
Name: "two",
Value: "two",
Print: true,
Filter: &Filter{Skip: true},
},
}

err := capComm.MergeParams(ctx, params)
if err != nil {
t.Error("unexpected", err)
}

v := capComm.params.Get("two")

if v != "" {
t.Error("unexpected v filtered", v)
}
}

func TestParamsFilterDuplicated(t *testing.T) {
ctx := context.Background()
capComm := NewCapComm(testMissionFile, stdlog.New())

params := []Param{
{
Name: "one",
Value: "here",
},
{
Name: "two",
Value: "this one",
Print: true,
},
{
Name: "two",
Value: "two",
Print: true,
Filter: &Filter{Skip: true},
},
}

err := capComm.MergeParams(ctx, params)
if err != nil {
t.Error("unexpected", err)
}

v := capComm.params.Get("two")

if v != "this one" {
t.Error("unexpected v picked wrong one", v)
}
}

func TestDirName(t *testing.T) {
if d := dirname("a/b/c"); d != "a/b" {
t.Error("unexpected", d)
Expand Down
76 changes: 76 additions & 0 deletions pkg/rocket/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
Copyright (c) 2021 The cirocket Authors (Neil Hemming)
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 rocket

import "runtime"

// IsFiltered returns true if the filter should be applied to exclude the item.
func (filter *Filter) IsFiltered() bool { //nolint:cyclop
if filter == nil {
return false
}

if filter.Skip {
return true
}

if len(filter.ExcludeArch) > 0 {
for _, a := range filter.ExcludeArch {
if a == runtime.GOARCH {
return true
}
}
}

if len(filter.ExcludeOS) > 0 {
for _, o := range filter.ExcludeOS {
if o == runtime.GOOS {
return true
}
}
}

if len(filter.IncludeArch) > 0 {
included := false
for _, a := range filter.IncludeArch {
if a == runtime.GOARCH {
included = true
break
}
}

if !included {
return true
}
}

if len(filter.IncludeOS) > 0 {
included := false
for _, o := range filter.IncludeOS {
if o == runtime.GOOS {
included = true
break
}
}

if !included {
return true
}
}

return false
}
Loading

0 comments on commit b58d4db

Please sign in to comment.