-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial implementation with playbook matching
- Loading branch information
Showing
12 changed files
with
804 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,3 +10,5 @@ | |
|
||
# Output of the go coverage tool, specifically when used with LiteIDE | ||
*.out | ||
vendor | ||
zeno |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,19 @@ | ||
# zeno | ||
CLI tool to examine ansible playbooks affected by git changes | ||
|
||
## Installation | ||
``` | ||
$ go get -u github.com/meomap/zeno | ||
``` | ||
## Usage | ||
``` | ||
$ zeno -files="$(git diff $COMMIT_HASH_BEFORE $COMMIT_HASH_AFTER --name-only)" -playbooks=qa/site.yml,staging/site.yml | ||
qa/site.yml,staging/site.yml | ||
``` | ||
## Features | ||
|
||
- Ansible playbook supported. | ||
|
||
## Contributing | ||
|
||
Bug reports & pull requests are welcome. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
module github.com/meomap/zeno | ||
|
||
require ( | ||
github.com/alecthomas/gometalinter v2.0.6+incompatible // indirect | ||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/davidrjenni/reftools v0.0.0-20180509164333-3813a62570d2 // indirect | ||
github.com/fatih/gomodifytags v0.0.0-20180826164257-7987f52a7108 // indirect | ||
github.com/google/shlex v0.0.0-20150127133951-6f45313302b9 // indirect | ||
github.com/nicksnyder/go-i18n v1.10.0 // indirect | ||
github.com/nsf/gocode v0.0.0-20180502111240-9d1e0378d35b // indirect | ||
github.com/pelletier/go-toml v1.2.0 // indirect | ||
github.com/pkg/errors v0.8.0 | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
github.com/stretchr/testify v1.2.2 | ||
golang.org/x/tools v0.0.0-20180826000951-f6ba57429505 // indirect | ||
gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c // indirect | ||
gopkg.in/yaml.v2 v2.2.1 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
github.com/alecthomas/gometalinter v2.0.6+incompatible h1:Z7mLBD7u7kjfsxa/edMutwqGygQI//inz0s+FCRmnvw= | ||
github.com/alecthomas/gometalinter v2.0.6+incompatible/go.mod h1:qfIpQGGz3d+NmgyPBqv+LSh50emm1pt72EtcX2vKYQk= | ||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= | ||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/davidrjenni/reftools v0.0.0-20180509164333-3813a62570d2 h1:s9FFqeh2hSpBk09NiFLaHHQddrrLBlTrT2p26sPUfd4= | ||
github.com/davidrjenni/reftools v0.0.0-20180509164333-3813a62570d2/go.mod h1:8o/GRMvsb9VyFbSEZGXfa0dkSXml4G23W0D/h9FksWM= | ||
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= | ||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= | ||
github.com/fatih/gomodifytags v0.0.0-20180826164257-7987f52a7108 h1:CIkmEYX6OO/UB9pBSdFvVlhkpT0pXjqXYo9lMmGVaLI= | ||
github.com/fatih/gomodifytags v0.0.0-20180826164257-7987f52a7108/go.mod h1:p2/x7bnOQsbq/deXsDIlj2yLiKFGPkD2nuoYqwn8R4Y= | ||
github.com/fatih/structtag v1.0.0 h1:pTHj65+u3RKWYPSGaU290FpI/dXxTaHdVwVwbcPKmEc= | ||
github.com/fatih/structtag v1.0.0/go.mod h1:IKitwq45uXL/yqi5mYghiD3w9H6eTOvI9vnk8tXMphA= | ||
github.com/google/shlex v0.0.0-20150127133951-6f45313302b9 h1:JM174NTeGNJ2m/oLH3UOWOvWQQKd+BoL3hcSCUWFLt0= | ||
github.com/google/shlex v0.0.0-20150127133951-6f45313302b9/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= | ||
github.com/nicksnyder/go-i18n v1.10.0 h1:5AzlPKvXBH4qBzmZ09Ua9Gipyruv6uApMcrNZdo96+Q= | ||
github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q= | ||
github.com/nsf/gocode v0.0.0-20180502111240-9d1e0378d35b h1:agMWdTHUzw9qlSSiKEz7SwXP2ZmLesKkmWYaS0K2GLk= | ||
github.com/nsf/gocode v0.0.0-20180502111240-9d1e0378d35b/go.mod h1:6Q8/OMaaKAgTX7/jt2bOXVDrm1eJhoNd+iwzghR7jvs= | ||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= | ||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= | ||
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= | ||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= | ||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | ||
golang.org/x/tools v0.0.0-20180824175216-6c1c5e93cdc1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
golang.org/x/tools v0.0.0-20180826000951-f6ba57429505 h1:A7IWEQZw8yuHhjAcYjsnhC1/6KYEknVQYRVmhut3Gzk= | ||
golang.org/x/tools v0.0.0-20180826000951-f6ba57429505/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c h1:vTxShRUnK60yd8DZU+f95p1zSLj814+5CuEh7NjF2/Y= | ||
gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c/go.mod h1:3HH7i1SgMqlzxCcBmUHW657sD4Kvv9sC3HpL3YukzwA= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= | ||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package loader | ||
|
||
import ( | ||
"io/ioutil" | ||
"os" | ||
"path" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
// DataSource defines common interface for data loading | ||
type DataSource interface { | ||
ReadFile(string) ([]byte, error) | ||
ReadDir(string) ([]string, error) | ||
IsExist(string) (bool, error) | ||
} | ||
|
||
// MemoryLoader implements IO operations for testing | ||
type MemoryLoader struct { | ||
files map[string][]byte | ||
dirs map[string][]string | ||
} | ||
|
||
// ReadFile returns byte content given preload file name | ||
func (ml MemoryLoader) ReadFile(name string) ([]byte, error) { | ||
content, ok := ml.files[name] | ||
if !ok { | ||
return nil, errors.Errorf("file %s not exist", name) | ||
} | ||
return content, nil | ||
} | ||
|
||
// SetFile update stored file's content | ||
func (ml *MemoryLoader) SetFile(name string, content []byte) { | ||
if ml.files == nil { | ||
ml.files = map[string][]byte{} | ||
} | ||
pathComps := strings.Split(name, string(filepath.Separator)) | ||
lenComps := len(pathComps) | ||
var ( | ||
subdir []byte | ||
ok bool | ||
parent string | ||
) | ||
for i := 0; i < lenComps-1; i++ { | ||
if i == 0 { | ||
parent = pathComps[i] | ||
} else { | ||
parent = path.Join(parent, pathComps[i]) | ||
} | ||
child := pathComps[i+1] | ||
if subdir, ok = ml.files[parent]; !ok { | ||
subdir = []byte(child) | ||
} else { | ||
updated := strings.Split(string(subdir), ",") | ||
updated = append(updated, child) | ||
subdir = []byte(strings.Join(updated, ",")) | ||
} | ||
ml.files[parent] = subdir | ||
} | ||
ml.files[name] = content | ||
} | ||
|
||
// ReadDir returns list of files' name under specified directory | ||
func (ml MemoryLoader) ReadDir(name string) ([]string, error) { | ||
content, ok := ml.files[name] | ||
if !ok { | ||
return nil, &os.PathError{Err: os.ErrNotExist} | ||
} | ||
children := strings.Split(string(content), ",") | ||
return children, nil | ||
} | ||
|
||
// IsExist returns true if given file name exists | ||
func (ml MemoryLoader) IsExist(name string) (ok bool, err error) { | ||
if _, ok = ml.files[name]; !ok { | ||
for dir := range ml.dirs { | ||
if strings.HasPrefix(dir, name) { | ||
ok = true | ||
break | ||
} | ||
} | ||
} | ||
return | ||
} | ||
|
||
// Clear reset in-mem data | ||
func (ml *MemoryLoader) Clear() { | ||
ml.files = nil | ||
ml.dirs = nil | ||
} | ||
|
||
// FileLoader implements IO operation on local disk file | ||
type FileLoader struct { | ||
} | ||
|
||
// ReadFile returns byte content given file name | ||
func (fl FileLoader) ReadFile(name string) ([]byte, error) { | ||
content, err := ioutil.ReadFile(name) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "ioutil.ReadFile name=%s", name) | ||
} | ||
return content, nil | ||
} | ||
|
||
// ReadDir returns list of files' name under specified directory | ||
func (fl FileLoader) ReadDir(name string) (out []string, err error) { | ||
var stats []os.FileInfo | ||
if stats, err = ioutil.ReadDir(name); err != nil { | ||
err = errors.Wrapf(err, "ioutil.ReadDir name=%s", name) | ||
return | ||
} | ||
for _, v := range stats { | ||
out = append(out, v.Name()) | ||
} | ||
return | ||
} | ||
|
||
// IsExist returns true if given file name exists | ||
func (fl FileLoader) IsExist(name string) (bool, error) { | ||
_, err := os.Stat(name) | ||
if err != nil { | ||
if os.IsNotExist(err) { | ||
return false, nil | ||
} | ||
return false, errors.Wrapf(err, "os.Stat name=%s", name) | ||
} | ||
return true, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// zeno is a command line tool to analyse ansible playbook dependencies | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"os" | ||
"path" | ||
"strings" | ||
|
||
"github.com/meomap/zeno/loader" | ||
"github.com/meomap/zeno/search" | ||
) | ||
|
||
func main() { | ||
var ( | ||
filesIn = flag.String("files", "", "names of changed files from command 'git diff $BEFORE $AFTER --name-only'") | ||
debug = flag.Bool("debug", false, "enable for verbose logging") | ||
pbsIn = flag.String("playbooks", "", "comma separated list of playbooks to examined") | ||
) | ||
flag.Parse() | ||
|
||
// required args | ||
if *pbsIn == "" || *filesIn == "" { | ||
flag.PrintDefaults() | ||
os.Exit(1) | ||
} | ||
if *debug == false { | ||
log.SetOutput(ioutil.Discard) | ||
} | ||
diffFiles := strings.Split(*filesIn, "\n") | ||
repoDir, err := os.Getwd() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
lenDiffs := len(diffFiles) | ||
// construct absolute path for input files | ||
for i := 0; i < lenDiffs; i++ { | ||
diffFiles[i] = path.Join(repoDir, diffFiles[i]) | ||
} | ||
pbFiles := strings.Split(*pbsIn, ",") | ||
lenPbs := len(pbFiles) | ||
log.Printf("Match against [%d] files", lenDiffs) | ||
log.Printf("Examine [%d] playbooks: %s\n", lenPbs, *pbsIn) | ||
|
||
ds := new(loader.FileLoader) | ||
var ( | ||
matched bool | ||
out []string | ||
) | ||
for i := 0; i < lenPbs; i++ { | ||
name := pbFiles[i] | ||
if matched, err = search.MatchPlaybook(name, diffFiles, repoDir, ds); err != nil { | ||
log.Fatal(err) | ||
} else if matched { | ||
out = append(out, name) | ||
} | ||
} | ||
fmt.Println(strings.Join(out, ",")) | ||
} | ||
|
||
func init() { | ||
log.SetFlags(log.LstdFlags | log.Lmicroseconds | log.Lshortfile) | ||
} |
Oops, something went wrong.