diff --git a/internal/services/blackwhitelist_test.go b/internal/services/blackwhitelist_test.go index ff8996cd..013b7dfe 100644 --- a/internal/services/blackwhitelist_test.go +++ b/internal/services/blackwhitelist_test.go @@ -1,10 +1,8 @@ -package services_test +package services import ( "encoding/json" "testing" - - "github.com/ca-gip/kubi/internal/services" "github.com/ca-gip/kubi/internal/utils" v12 "github.com/ca-gip/kubi/pkg/apis/cagip/v1" "github.com/ca-gip/kubi/pkg/types" @@ -42,7 +40,7 @@ func TestBlackWhiteList(t *testing.T) { t.Run("with_nil_object", func(t *testing.T) { - result := services.MakeBlackWhitelist(nil) + result := MakeBlackWhitelist(nil) assert.Equal(t, []string([]string{""}), result.Blacklist) assert.Equal(t, []string([]string{""}), result.Whitelist) }) @@ -50,7 +48,7 @@ func TestBlackWhiteList(t *testing.T) { t.Run("with_empty_map", func(t *testing.T) { blackWhitelistData := map[string]string{} - result := services.MakeBlackWhitelist(blackWhitelistData) + result := MakeBlackWhitelist(blackWhitelistData) assert.Equal(t, []string([]string{""}), result.Blacklist) assert.Equal(t, []string([]string{""}), result.Whitelist) }) @@ -61,7 +59,7 @@ func TestBlackWhiteList(t *testing.T) { "dzadz$Ùdzadza": "fefezfez, 6z556/*/R/ÉR*/", } - result := services.MakeBlackWhitelist(blackWhitelistData) + result := MakeBlackWhitelist(blackWhitelistData) assert.Equal(t, []string([]string{""}), result.Blacklist) assert.Equal(t, []string([]string{""}), result.Whitelist) }) @@ -72,7 +70,7 @@ func TestBlackWhiteList(t *testing.T) { "whitelist": "", } - result := services.MakeBlackWhitelist(blackWhitelistData) + result := MakeBlackWhitelist(blackWhitelistData) assert.Equal(t, []string([]string{"native-developpement", " native-integration"}), result.Blacklist) assert.Equal(t, []string([]string{""}), result.Whitelist) }) @@ -86,151 +84,270 @@ func TestGenerateProjects(t *testing.T) { Project: "native", Environment: "development", }, + { + Project: "native", + Environment: "integration", + }, + { + Project: "native", + Environment: "production", + }, } + + //WHITELIST - t.Run("with_empty_whitelist", func(t *testing.T) { + t.Run("blacklisted projects are deleted and no whithelisted projects are ignored", func(t *testing.T) { blackWhitelistData := map[string]string{ "blacklist": "native-development,native-integration", "whitelist": "", } + expectedCreate := []*types.Project{ + } + expectedDelete := []*types.Project{ + { + Project: "native", + Environment: "development", + }, + { + Project: "native", + Environment: "integration", + }, + } + expectedIgnore := []*types.Project{ + { + Project: "native", + Environment: "production", + }, + } - blackWhitelist := services.MakeBlackWhitelist(blackWhitelistData) + blackWhitelist := MakeBlackWhitelist(blackWhitelistData) utils.Config = &types.Config{Whitelist: true} - result := GenerateProjects(fakeProject, &blackWhitelist) - assert.Equal(t, []bool{false}, result) + gotCreated,gotDeleted,gotIgnored := GenerateProjects(fakeProject, &blackWhitelist) + assert.ElementsMatch(t,gotCreated,expectedCreate, "the expected create projects match created list ") + assert.ElementsMatch(t,gotDeleted,expectedDelete, "the expected delete projects match deleted list ") + assert.ElementsMatch(t,gotIgnored,expectedIgnore, "the expected ignore projects match ignored list") }) - t.Run("with_equal_whitelist", func(t *testing.T) { + t.Run("blacklist takes priority and no whitlisted projects are ignored", func(t *testing.T) { blackWhitelistData := map[string]string{ "blacklist": "native-development,native-integration", "whitelist": "native-development", } - blackWhitelist := services.MakeBlackWhitelist(blackWhitelistData) + expectedCreate := []*types.Project{ + } + + expectedDelete := []*types.Project{ + { + Project: "native", + Environment: "development", + }, + { + Project: "native", + Environment: "integration", + }, + } + + expectedIgnore := []*types.Project{ + { + Project: "native", + Environment: "production", + }, + } + blackWhitelist := MakeBlackWhitelist(blackWhitelistData) utils.Config = &types.Config{Whitelist: true} - result := GenerateProjects(fakeProject, &blackWhitelist) - assert.Equal(t, []bool{true}, result) + gotCreated,gotDeleted,gotIgnored := GenerateProjects(fakeProject, &blackWhitelist) + assert.ElementsMatch(t,gotCreated,expectedCreate, "the expected create projects match created list ") + assert.ElementsMatch(t,gotDeleted,expectedDelete, "the expected delete projects match deleted list ") + assert.ElementsMatch(t,gotIgnored,expectedIgnore, "the expected ignore projects match ignored list") }) - t.Run("with_not_equal_whitelist", func(t *testing.T) { + t.Run("no project is created unless explicitly defined in whitelist; blacklisted projects are deleted", func(t *testing.T) { blackWhitelistData := map[string]string{ "blacklist": "native-development,native-integration", - "whitelist": "native-divelopment", + "whitelist": "native-production", + } + + expectedCreate := []*types.Project{ + { + Project: "native", + Environment: "production", + }, + } + + expectedDelete := []*types.Project{ + { + Project: "native", + Environment: "development", + }, + { + Project: "native", + Environment: "integration", + }, + } + + expectedIgnore := []*types.Project{ } - blackWhitelist := services.MakeBlackWhitelist(blackWhitelistData) + blackWhitelist := MakeBlackWhitelist(blackWhitelistData) utils.Config = &types.Config{Whitelist: true} - result := GenerateProjects(fakeProject, &blackWhitelist) - assert.Equal(t, []bool{false}, result) + gotCreated,gotDeleted,gotIgnored := GenerateProjects(fakeProject, &blackWhitelist) + assert.ElementsMatch(t,gotCreated,expectedCreate, "the expected create projects match created list ") + assert.ElementsMatch(t,gotDeleted,expectedDelete, "the expected delete projects match deleted list ") + assert.ElementsMatch(t,gotIgnored,expectedIgnore, "the expected ignore projects match ignored list") }) - t.Run("with_faildata_whitelist", func(t *testing.T) { + t.Run("ignore all projects if confimap contains invalid data", func(t *testing.T) { blackWhitelistData := map[string]string{ "blaaeza": "rrzerzF", } - blackWhitelist := services.MakeBlackWhitelist(blackWhitelistData) + expectedCreate := []*types.Project{ + } + + expectedDelete := []*types.Project{ + } + + expectedIgnore := []*types.Project{ + { + Project: "native", + Environment: "development", + }, + { + Project: "native", + Environment: "integration", + }, + { + Project: "native", + Environment: "production", + }, + } + blackWhitelist := MakeBlackWhitelist(blackWhitelistData) utils.Config = &types.Config{Whitelist: true} - result := GenerateProjects(fakeProject, &blackWhitelist) - assert.Equal(t, []bool{false}, result) + gotCreated,gotDeleted,gotIgnored := GenerateProjects(fakeProject, &blackWhitelist) + assert.ElementsMatch(t,gotCreated,expectedCreate, "the expected create projects match created list ") + assert.ElementsMatch(t,gotDeleted,expectedDelete, "the expected delete projects match deleted list ") + assert.ElementsMatch(t,gotIgnored,expectedIgnore, "the expected ignore projects match ignored list") }) //BLACKLIST - t.Run("with_empty_blacklist", func(t *testing.T) { + t.Run("Projects are created unless explicitly blacklisted", func(t *testing.T) { blackWhitelistData := map[string]string{ "blacklist": "", "whitelist": "native-development", } - blackWhitelist := services.MakeBlackWhitelist(blackWhitelistData) - - utils.Config = &types.Config{Whitelist: false} - result := GenerateProjects(fakeProject, &blackWhitelist) - assert.Equal(t, []bool{false}, result) - }) + expectedCreate := []*types.Project{ + { + Project: "native", + Environment: "development", + }, + { + Project: "native", + Environment: "integration", + }, + { + Project: "native", + Environment: "production", + }, + } - t.Run("with_equal_blacklist", func(t *testing.T) { + expectedDelete := []*types.Project{ + } - blackWhitelistData := map[string]string{ - "blacklist": "native-development,native-integration", - "whitelist": "native-development", + expectedIgnore := []*types.Project{ } - blackWhitelist := services.MakeBlackWhitelist(blackWhitelistData) + blackWhitelist := MakeBlackWhitelist(blackWhitelistData) utils.Config = &types.Config{Whitelist: false} - result := GenerateProjects(fakeProject, &blackWhitelist) - assert.Equal(t, []bool{true}, result) + gotCreated,gotDeleted,gotIgnored := GenerateProjects(fakeProject, &blackWhitelist) + assert.ElementsMatch(t,gotCreated,expectedCreate, "the expected create projects match created list ") + assert.ElementsMatch(t,gotDeleted,expectedDelete, "the expected delete projects match deleted list ") + assert.ElementsMatch(t,gotIgnored,expectedIgnore, "the expected ignore projects match ignored list") }) - t.Run("with_not_equal_blacklist", func(t *testing.T) { + + + t.Run("project don't require whitelisting to be created", func(t *testing.T) { blackWhitelistData := map[string]string{ - "blacklist": "native-devilopment,native-integration", - "whitelist": "native-divelopment", + "blacklist": "native-development,native-integration", + "whitelist": "", + } + expectedCreate := []*types.Project{ + { + Project: "native", + Environment: "production", + }, } - blackWhitelist := services.MakeBlackWhitelist(blackWhitelistData) + expectedDelete := []*types.Project{ + { + Project: "native", + Environment: "development", + }, + { + Project: "native", + Environment: "integration", + }, + } + + expectedIgnore := []*types.Project{ + } + + blackWhitelist := MakeBlackWhitelist(blackWhitelistData) utils.Config = &types.Config{Whitelist: false} - result := GenerateProjects(fakeProject, &blackWhitelist) - assert.Equal(t, []bool{false}, result) + gotCreated,gotDeleted,gotIgnored := GenerateProjects(fakeProject, &blackWhitelist) + assert.ElementsMatch(t,gotCreated,expectedCreate, "the expected create projects match created list ") + assert.ElementsMatch(t,gotDeleted,expectedDelete, "the expected delete projects match deleted list ") + assert.ElementsMatch(t,gotIgnored,expectedIgnore, "the expected ignore projects match ignored list") }) - t.Run("with_faildata_blacklist", func(t *testing.T) { + t.Run("all projects are created if confimap contains invalid data", func(t *testing.T) { blackWhitelistData := map[string]string{ "blaaeza": "rrzerzF", } + expectedCreate := []*types.Project{ + { + Project: "native", + Environment: "development", + }, + { + Project: "native", + Environment: "integration", + }, + { + Project: "native", + Environment: "production", + }, + } - blackWhitelist := services.MakeBlackWhitelist(blackWhitelistData) - - utils.Config = &types.Config{Whitelist: false} - result := GenerateProjects(fakeProject, &blackWhitelist) - assert.Equal(t, []bool{false}, result) - }) - -} + expectedDelete := []*types.Project{ + } -// Mock of GenerateProjects func from provisionner. TODO : refacto to be testable -func GenerateProjects(context []*types.Project, blackWhiteList *types.BlackWhitelist) []bool { - - var boolList []bool - - for _, auth := range context { - - // if whitelist boolean set we search namespace in configmap whitelist - if utils.Config.Whitelist { // if configmap with whitelist exist and not empty - if blackWhiteList.Whitelist[0] != "" && utils.Include(blackWhiteList.Whitelist, auth.Namespace()) { - utils.Log.Info().Msgf("Project %s is whitelisted", auth.Namespace()) - boolList = append(boolList, true) - } else { - utils.Log.Error().Msgf("Cannot find project %s in whitelist", auth.Namespace()) - boolList = append(boolList, false) - } - } else if blackWhiteList.Blacklist[0] != "" { // if configmap with blacklist exist and not empty - if utils.Include(blackWhiteList.Blacklist, auth.Namespace()) { - utils.Log.Info().Msgf("delete project %s in blacklist", auth.Namespace()) - boolList = append(boolList, true) - } else { - utils.Log.Info().Msgf("Cannot find project %s in blacklist", auth.Namespace()) - boolList = append(boolList, false) - } - } else { // if configmap not exist and bool whitelist is false - boolList = append(boolList, false) + expectedIgnore := []*types.Project{ } - } + blackWhitelist := MakeBlackWhitelist(blackWhitelistData) - return boolList -} + utils.Config = &types.Config{Whitelist: false} + gotCreated,gotDeleted,gotIgnored := GenerateProjects(fakeProject, &blackWhitelist) + assert.ElementsMatch(t,gotCreated,expectedCreate, "the expected create projects match created list ") + assert.ElementsMatch(t,gotDeleted,expectedDelete, "the expected delete projects match deleted list ") + assert.ElementsMatch(t,gotIgnored,expectedIgnore, "the expected ignore projects match ignored list") + }) + +} \ No newline at end of file diff --git a/internal/services/provisionner.go b/internal/services/provisionner.go index 14f90eed..53dd0a97 100644 --- a/internal/services/provisionner.go +++ b/internal/services/provisionner.go @@ -61,36 +61,47 @@ func GenerateResources() error { blackWhiteList = MakeBlackWhitelist(blacklistCM.Data) } - GenerateProjects(auths, &blackWhiteList) + createdproject, deletedprojects, ignoredProjects := GenerateProjects(auths, &blackWhiteList) + for _, project := range ignoredProjects { + utils.Log.Error().Msgf("Cannot find project %s in whitelist", project.Namespace()) + } + for _, project := range deletedprojects { + utils.Log.Info().Msgf("delete project %s in blacklist", project.Namespace()) + deleteProject(project) + } + // now that the project is well categorized we know that a project cannot be at the same time to be deleted and to be generated + for _, project := range createdproject { + utils.Log.Info().Msgf("Project %s is whitelisted", project.Namespace()) + generateProject(project) + } return nil } // A loop wrapper for generateProject // splitted for unit test ! -func GenerateProjects(context []*types.Project, blackWhiteList *types.BlackWhitelist) { +func GenerateProjects(context []*types.Project, blackWhiteList *types.BlackWhitelist) ([]*types.Project, []*types.Project, []*types.Project) { + var createdProjects, deletedProjects, ignoredProjects []*types.Project for _, auth := range context { - // if whitelist boolean set we search namespace in configmap whitelist - if utils.Config.Whitelist { // if configmap with whitelist exist and not empty - if blackWhiteList.Whitelist[0] != "" && utils.Include(blackWhiteList.Whitelist, auth.Namespace()) { - utils.Log.Info().Msgf("Project %s is whitelisted", auth.Namespace()) - generateProject(auth) - } else { - utils.Log.Error().Msgf("Cannot find project %s in whitelist", auth.Namespace()) - } - } else if blackWhiteList.Blacklist[0] != "" { // if configmap with blacklist exist and not empty - if utils.Include(blackWhiteList.Blacklist, auth.Namespace()) { - utils.Log.Info().Msgf("delete project %s in blacklist", auth.Namespace()) - deleteProject(auth) - } else { - utils.Log.Info().Msgf("Cannot find project %s in blacklist", auth.Namespace()) - } - } else { // if configmap not exist and bool whitelist is false - generateProject(auth) + switch { + //we treat blacklisted projects as a priority, project will be deleted + case blackWhiteList.Blacklist[0] != "" && utils.Include(blackWhiteList.Blacklist, auth.Namespace()): + deletedProjects = append(deletedProjects,auth) + continue + // If whitelist is enabled, do not create project unless it's explictly mentioned + case utils.Config.Whitelist == true && utils.Include(blackWhiteList.Whitelist, auth.Namespace()): + createdProjects = append(createdProjects,auth) + //project will be ignored if whitelist is enabled and project not present on whitelisted projects + case utils.Config.Whitelist == true && !utils.Include(blackWhiteList.Whitelist, auth.Namespace()): + ignoredProjects = append(ignoredProjects,auth) + //project will be created if whitelist is disabled and no projects in blacklist + default: + createdProjects = append(createdProjects,auth) } - } + + return createdProjects, deletedProjects, ignoredProjects } // generate a project config or update it if exists