Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add option to recursive apply directory #5

Merged
merged 1 commit into from
Feb 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions cmd/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import (
)

var (
applyFile string
applyProject string
applyFile string
applyProject string
applyRecursive bool

applyCmd = &cobra.Command{
Use: "apply",
Expand All @@ -20,14 +21,15 @@ var (
}
r := rpdac.NewReportPortal(c)

return r.Apply(applyProject, applyFile)
return r.Apply(applyProject, applyFile, applyRecursive)
},
}
)

func init() {
applyCmd.Flags().StringVarP(&applyFile, "file", "f", "", "YAML file")
applyCmd.Flags().StringVarP(&applyProject, "project", "p", "", "ReportPortal Project")
applyCmd.Flags().BoolVarP(&applyRecursive, "recursive", "r", false, "If file is a directory it will recusive apply all objects in it")

applyCmd.MarkFlagRequired("file")
applyCmd.MarkFlagRequired("project")
Expand Down
2 changes: 0 additions & 2 deletions pkg/rpdac/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ func (s *FilterService) Update(project string, current, target Object) error {
if err != nil {
return fmt.Errorf("error updating filter \"%s\": %w", targetFilter.Name, err)
}

log.Printf("update \"%s\" filter", targetFilter.Name)
return nil
}

Expand Down
59 changes: 58 additions & 1 deletion pkg/rpdac/reportportal.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package rpdac

import (
"errors"
"fmt"
"io/fs"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"

"github.com/b1zzu/reportportal-dashboards-as-code/pkg/reportportal"
"gopkg.in/yaml.v2"
Expand Down Expand Up @@ -122,7 +127,59 @@ func (r *ReportPortal) Create(project, file string) error {
return nil
}

func (r *ReportPortal) Apply(project, file string) error {
func (r *ReportPortal) Apply(project, file string, recursive bool) error {

info, err := os.Stat(file)
if os.IsNotExist(err) {
return fmt.Errorf("error '%s' is not a vailid file or directory: %w", file, err)
} else if err != nil {
return err
}

if info.IsDir() {

if !recursive {
return fmt.Errorf("error '%s' is a directory, use the `-r` option if you want to recursive apply all object in the directory", file)
}

failed := false
err = filepath.WalkDir(file, func(path string, d fs.DirEntry, err error) error {
if err != nil {
log.Printf("Unknow error: %s", err)
return nil
}

if d.IsDir() {
// skip directories
return nil
}

if !strings.HasSuffix(d.Name(), ".yml") && !strings.HasSuffix(d.Name(), ".yaml") {
log.Printf("Ignore file '%s' because only .yml|.yaml are supported", path)
return nil
}

if err := r.ApplyFile(project, path); err != nil {
failed = true
log.Printf("Failed to apply file '%s': %s", path, err)
}
return nil
})
if err != nil {
return err
}

if failed {
return errors.New("error applying one or more objects")
}
return nil

} else {
return r.ApplyFile(project, file)
}
}

func (r *ReportPortal) ApplyFile(project, file string) error {

fileBytes, err := ioutil.ReadFile(file)
if err != nil {
Expand Down
147 changes: 144 additions & 3 deletions pkg/rpdac/reportportal_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package rpdac

import (
"fmt"
"io/ioutil"
"os"
"testing"
Expand Down Expand Up @@ -268,7 +269,7 @@ description: Test desc
r := NewReportPortal(nil)
r.Dashboard = mockService

err := r.Apply("test_project", file)
err := r.Apply("test_project", file, false)
if err != nil {
t.Errorf("Apply retunred error: %s", err)
}
Expand Down Expand Up @@ -317,7 +318,7 @@ description: Test new desc
r := NewReportPortal(nil)
r.Dashboard = mockService

err := r.Apply("test_project", file)
err := r.Apply("test_project", file, false)
if err != nil {
t.Errorf("Apply retunred error: %s", err)
}
Expand Down Expand Up @@ -355,10 +356,150 @@ description: Test desc
r := NewReportPortal(nil)
r.Dashboard = mockService

err := r.Apply("test_project", file)
err := r.Apply("test_project", file, false)
if err != nil {
t.Errorf("Apply retunred error: %s", err)
}

testDeepEqual(t, mockService.Counter, MockServiceCounter{GetByName: 1, Create: 1})
}

func tempDir(t *testing.T) (string, func()) {
t.Helper()

dir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatalf("failed to create tmp directory: %s", err)
}
return dir, func() { os.RemoveAll(dir) }
}

func mkdir(t *testing.T, name string) {
t.Helper()

err := os.Mkdir(name, 0755)
if err != nil {
t.Fatalf("failed to create dir '%s': %s", name, err)
}
}

func writeFile(t *testing.T, filename, data string) {
t.Helper()

err := ioutil.WriteFile(filename, []byte(data), 0644)
if err != nil {
t.Fatalf("failed to write file '%s': %s", filename, err)
}
}

func TestApply_Directory(t *testing.T) {

dir, clean := tempDir(t)
defer clean()

writeFile(t, dir+"/dashboard.yml", `kind: Dashboard
name: Test
`)
writeFile(t, dir+"/skipme.xml", `Some randome stuff`)
mkdir(t, dir+"/subfolder")
writeFile(t, dir+"/subfolder/filter.yaml", `kind: Filter
name: Test
`)

mockDashboardService := &MockService{
GetByNameM: func(project, name string) (Object, error) {
testEqual(t, project, "test_project")
testEqual(t, name, "Test")
return nil, nil
},
CreateM: func(project string, o Object) error {
testEqual(t, project, "test_project")
testDeepEqual(t, o, &Dashboard{
Kind: DashboardKind,
Name: "Test",
}, cmpopts.IgnoreUnexported(Dashboard{}))
return nil
},
}
mockFilterService := &MockService{
GetByNameM: func(project, name string) (Object, error) {
testEqual(t, project, "test_project")
testEqual(t, name, "Test")
return &Filter{
Kind: FilterKind,
Name: "Test",
}, nil
},
}
r := NewReportPortal(nil)
r.Dashboard = mockDashboardService
r.Filter = mockFilterService

err := r.Apply("test_project", dir, true)
if err != nil {
t.Errorf("Apply retunred error: %s", err)
}

testDeepEqual(t, mockDashboardService.Counter, MockServiceCounter{GetByName: 1, Create: 1})
testDeepEqual(t, mockFilterService.Counter, MockServiceCounter{GetByName: 1})
}

func TestApply_DirectoryWithoutRecursive(t *testing.T) {

dir, clean := tempDir(t)
defer clean()
r := NewReportPortal(nil)

err := r.Apply("test_project", dir, false)
if err == nil {
t.Errorf("Want err but got nil")
} else {
want := fmt.Sprintf("error '%s' is a directory, use the `-r` option if you want to recursive apply all object in the directory", dir)
if err.Error() != want {
t.Errorf("Want err '%s' but got '%s'", want, err)
}
}
}

func TestApply_DirectoryWithWrongObject(t *testing.T) {

dir, clean := tempDir(t)
defer clean()

writeFile(t, dir+"/dashboard.yml", `kind: Something
name: Test
`)
writeFile(t, dir+"/skipme.xml", `Some randome stuff`)
mkdir(t, dir+"/subfolder")
writeFile(t, dir+"/subfolder/filter.yaml", `kind: Filter
name: Test
`)

mockDashboardService := &MockService{}
mockFilterService := &MockService{
GetByNameM: func(project, name string) (Object, error) {
testEqual(t, project, "test_project")
testEqual(t, name, "Test")
return &Filter{
Kind: FilterKind,
Name: "Test",
}, nil
},
}
r := NewReportPortal(nil)
r.Dashboard = mockDashboardService
r.Filter = mockFilterService

err := r.Apply("test_project", dir, true)
if err == nil {
t.Errorf("Want err but got nil")
} else {
want := "error applying one or more objects"
if err.Error() != want {
t.Errorf("Want err '%s' but got '%s'", want, err)
}
}

testDeepEqual(t, mockDashboardService.Counter, MockServiceCounter{})
testDeepEqual(t, mockFilterService.Counter, MockServiceCounter{GetByName: 1})
}