add scope feature + lint fixes

This commit is contained in:
Alex Goodman 2020-05-12 20:43:46 -04:00
parent 1e5c7bb5c7
commit 11b2b1ab45
No known key found for this signature in database
GPG key ID: 86E2870463D5E890
9 changed files with 194 additions and 19 deletions

View file

@ -9,41 +9,41 @@ linters:
- dogsled
- dupl
- errcheck
# - funlen
- gochecknoinits
# - gocognit
- funlen
- gocognit
- goconst
# - gocritic
- gocritic
- gocyclo
- gofmt
- goimports
# - golint
- golint
- gomnd
- goprintffuncname
- gosec
- gosimple
- govet
- ineffassign
# - interfacer
# - lll
- interfacer
- lll
- misspell
- nakedret
- nolintlint
- rowserrcheck
# - scopelint
- scopelint
- staticcheck
- structcheck
# - stylecheck
- stylecheck
- typecheck
- unconvert
- unparam
- unused
- varcheck
# - whitespace
- whitespace
- prealloc
- asciicheck
# do not enable...
# - gochecknoinits
# - gochecknoglobals
# - godot
# - godox

View file

@ -2,21 +2,22 @@ package cmd
import (
"fmt"
"github.com/spf13/cobra"
"os"
"github.com/spf13/cobra"
)
const ApplicationName = "imgbom"
var rootOptions struct {
cfgFile string
cfgFile string
}
var rootCmd = &cobra.Command{
Use: ApplicationName,
Short: "A container image BOM tool",
Long: `todo.`,
Run: doRunCmd,
Run: doRunCmd,
}
func Execute() {
@ -37,4 +38,4 @@ func loadApplicationConfig() {
func doRunCmd(cmd *cobra.Command, args []string) {
}
}

View file

@ -1,9 +1,9 @@
package cmd
import (
"fmt"
"fmt"
"github.com/spf13/cobra"
"github.com/spf13/cobra"
)
type Version struct {
@ -30,4 +30,4 @@ func SetVersion(v *Version) {
func printVersion(cmd *cobra.Command, args []string) {
fmt.Printf("%s %s\n", ApplicationName, version.Version)
}
}

2
go.mod
View file

@ -3,7 +3,7 @@ module github.com/anchore/imgbom
go 1.14
require (
github.com/anchore/stereoscope v0.0.0-20200512135733-57b1df994b57 // indirect
github.com/anchore/stereoscope v0.0.0-20200512135733-57b1df994b57
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/mitchellh/mapstructure v1.3.0 // indirect
github.com/pelletier/go-toml v1.7.0 // indirect

23
imgbom/scope/option.go Normal file
View file

@ -0,0 +1,23 @@
package scope
const (
UnknownScope Option = iota
SquashedScope
AllLayersScope
)
type Option int
var optionStr = []string{
"UnknownScope",
"Squashed",
"AllLayers",
}
func (o Option) String() string {
if int(o) >= len(optionStr) || int(o) < 0 {
return optionStr[0]
}
return optionStr[o]
}

View file

@ -0,0 +1,17 @@
package scope
import (
"fmt"
"testing"
)
func TestOptionStringerBoundary(t *testing.T) {
var _ fmt.Stringer = Option(0)
for _, c := range []int{-1, 0, 3} {
option := Option(c)
if option.String() != UnknownScope.String() {
t.Errorf("expected Option(%d) to be unknown, found '%+v'", c, option)
}
}
}

44
imgbom/scope/scope.go Normal file
View file

@ -0,0 +1,44 @@
package scope
import (
"fmt"
"github.com/anchore/stereoscope/pkg/image"
"github.com/anchore/stereoscope/pkg/tree"
)
type Scope struct {
Option Option
Trees []*tree.FileTree
}
func NewScope(img *image.Image, option Option) (Scope, error) {
var trees = make([]*tree.FileTree, 0)
if img == nil {
return Scope{}, fmt.Errorf("no image given")
}
switch option {
case SquashedScope:
if img.SquashedTree == nil {
return Scope{}, fmt.Errorf("the image does not have have a squashed tree")
}
trees = append(trees, img.SquashedTree)
case AllLayersScope:
if len(img.Layers) == 0 {
return Scope{}, fmt.Errorf("the image does not contain any layers")
}
for _, layer := range img.Layers {
trees = append(trees, layer.Tree)
}
default:
return Scope{}, fmt.Errorf("bad option provided: %+v", option)
}
return Scope{
Option: option,
Trees: trees,
}, nil
}

View file

@ -0,0 +1,90 @@
package scope
import (
"github.com/anchore/stereoscope/pkg/image"
"github.com/anchore/stereoscope/pkg/tree"
"testing"
)
func testScopeImage(t *testing.T) *image.Image {
t.Helper()
one := image.NewLayer(0, nil)
one.Tree = tree.NewFileTree()
one.Tree.AddPath("/tree/first/path.txt")
two := image.NewLayer(1, nil)
two.Tree = tree.NewFileTree()
two.Tree.AddPath("/tree/second/path.txt")
i := image.NewImage(nil)
i.Layers = []image.Layer{one, two}
err := i.Squash()
if err != nil {
t.Fatal("could not squash test image trees")
}
return i
}
func TestScope(t *testing.T) {
refImg := testScopeImage(t)
cases := []struct {
name string
img *image.Image
option Option
expectedTrees []*tree.FileTree
err bool
}{
{
name: "AllLayersGoCase",
option: AllLayersScope,
img: testScopeImage(t),
expectedTrees: []*tree.FileTree{refImg.Layers[0].Tree, refImg.Layers[1].Tree},
},
{
name: "SquashedGoCase",
option: SquashedScope,
img: testScopeImage(t),
expectedTrees: []*tree.FileTree{refImg.SquashedTree},
},
{
name: "MissingImage",
option: SquashedScope,
err: true,
},
{
name: "MissingSquashedTree",
option: SquashedScope,
img: image.NewImage(nil),
err: true,
},
{
name: "NoLayers",
option: AllLayersScope,
img: image.NewImage(nil),
err: true,
},
}
for _, c := range cases {
actual, err := NewScope(c.img, c.option)
if err == nil && c.err {
t.Fatal("expected an error but did not find one")
} else if err != nil && !c.err {
t.Fatal("expected no error but found one:", err)
}
if len(actual.Trees) != len(c.expectedTrees) {
t.Fatalf("mismatched tree lengths: %d!=%d", len(actual.Trees), len(c.expectedTrees))
}
for idx, at := range actual.Trees {
if !at.Equal(c.expectedTrees[idx]) {
t.Error("mismatched tree @ idx", idx)
}
}
}
}

View file

@ -18,4 +18,4 @@ func main() {
})
cmd.Execute()
}
}