From 750625ab159499feb3464011ff2440331eebbd15 Mon Sep 17 00:00:00 2001 From: Michael Stergianis <54287016+pivotal-michael-stergianis@users.noreply.github.com> Date: Mon, 24 Feb 2020 11:12:10 -0500 Subject: [PATCH] Config updater user actions (#1) * Lingering `pivotalservices -> pivotal-michael-stergianis` name changes * allow users of cf-mgmt to add users to orgs and spaces using a library like interface --- README.md | 10 +- ci/dev-build-pipeline.yml | 2 +- ci/pipeline.yml | 6 +- ci/tasks/build.sh | 14 +- ci/tasks/runTests.sh | 2 +- config/config.go | 4 + config/usermgmt.go | 14 ++ config/yaml_config.go | 65 ++++++++ config/yaml_config_test.go | 176 ++++++++++++++++++++ glide.lock | 18 +- glide.yaml | 2 +- pipelines/sync-docker-image-to-internal.yml | 2 +- uaa/users_test.go | 2 +- 13 files changed, 286 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index c9383783..ddbe9b08 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ platform: linux image_resource: type: docker-image - source: {repository: pivotalservices/cf-mgmt, tag: "0.0.91"} + source: {repository: pivotal-michael-stergianis/cf-mgmt, tag: "0.0.91"} inputs: - name: config-repo @@ -43,7 +43,7 @@ If there's already a configured foundation that you want to start using cf-mgmt ### Install -Compiled [releases](https://github.com/pivotalservices/cf-mgmt/releases) are available on Github. +Compiled [releases](https://github.com/pivotal-michael-stergianis/cf-mgmt/releases) are available on Github. Download the binary for your platform and place it somewhere on your path. Don't forget to `chmod +x` the file on Linux and macOS. @@ -165,9 +165,9 @@ To build the binary yourself, follow these steps: - Install `Go`. - Install [Glide](https://github.com/Masterminds/glide), a dependency management tool for Go. - Clone the repo: - - `mkdir -p $(go env GOPATH)/src/github.com/pivotalservices` - - `cd $(go env GOPATH)/src/github.com/pivotalservices` - - `git clone git@github.com:pivotalservices/cf-mgmt.git` + - `mkdir -p $(go env GOPATH)/src/github.com/pivotal-michael-stergianis` + - `cd $(go env GOPATH)/src/github.com/pivotal-michael-stergianis` + - `git clone git@github.com:pivotal-michael-stergianis/cf-mgmt.git` - Install dependencies: - `cd cf-mgmt` - `glide install` diff --git a/ci/dev-build-pipeline.yml b/ci/dev-build-pipeline.yml index 011a5db7..24546d93 100644 --- a/ci/dev-build-pipeline.yml +++ b/ci/dev-build-pipeline.yml @@ -2,7 +2,7 @@ resources: - name: source type: git source: - uri: git@github.com:pivotalservices/cf-mgmt.git + uri: git@github.com:pivotal-michael-stergianis/cf-mgmt.git branch: {{dev-build-branch}} private_key: {{git-ssh-key}} ignore_paths: ["README.md","docs/*"] diff --git a/ci/pipeline.yml b/ci/pipeline.yml index 51d3a3d1..98987075 100644 --- a/ci/pipeline.yml +++ b/ci/pipeline.yml @@ -10,7 +10,7 @@ resources: - name: source type: git source: - uri: git@github.com:pivotalservices/cf-mgmt.git + uri: git@github.com:pivotal-michael-stergianis/cf-mgmt.git branch: master private_key: {{git-ssh-key}} ignore_paths: ["README.md","docs/*"] @@ -18,7 +18,7 @@ resources: - name: draft-cfmgmt-resource type: github-release source: - owner: pivotalservices + owner: pivotal-michael-stergianis repository: cf-mgmt access_token: {{github-token}} drafts: true @@ -26,7 +26,7 @@ resources: - name: releases type: github-release source: - owner: pivotalservices + owner: pivotal-michael-stergianis repository: cf-mgmt access_token: {{github-token}} diff --git a/ci/tasks/build.sh b/ci/tasks/build.sh index 4f4c961c..acc9b8ca 100755 --- a/ci/tasks/build.sh +++ b/ci/tasks/build.sh @@ -34,18 +34,18 @@ else fi echo "next version should be: ${DRAFT_VERSION}" -WORKING_DIR=$GOPATH/src/github.com/pivotalservices/cf-mgmt +WORKING_DIR=$GOPATH/src/github.com/pivotal-michael-stergianis/cf-mgmt mkdir -p ${WORKING_DIR} cp -R ${SOURCE_DIR}/* ${WORKING_DIR}/. cd ${WORKING_DIR} glide install -CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ${OUTPUT_DIR}/cf-mgmt-linux -ldflags "-X github.com/pivotalservices/cf-mgmt/configcommands.VERSION=${VERSION} -X github.com/pivotalservices/cf-mgmt/configcommands.COMMIT=${COMMIT}" cmd/cf-mgmt/main.go -GOOS=darwin GOARCH=amd64 go build -o ${OUTPUT_DIR}/cf-mgmt-osx -ldflags "-X github.com/pivotalservices/cf-mgmt/configcommands.VERSION=${VERSION} -X github.com/pivotalservices/cf-mgmt/configcommands.COMMIT=${COMMIT}" cmd/cf-mgmt/main.go -GOOS=windows GOARCH=amd64 go build -o ${OUTPUT_DIR}/cf-mgmt.exe -ldflags "-X github.com/pivotalservices/cf-mgmt/configcommands.VERSION=${VERSION} -X github.com/pivotalservices/cf-mgmt/configcommands.COMMIT=${COMMIT}" cmd/cf-mgmt/main.go +CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ${OUTPUT_DIR}/cf-mgmt-linux -ldflags "-X github.com/pivotal-michael-stergianis/cf-mgmt/configcommands.VERSION=${VERSION} -X github.com/pivotal-michael-stergianis/cf-mgmt/configcommands.COMMIT=${COMMIT}" cmd/cf-mgmt/main.go +GOOS=darwin GOARCH=amd64 go build -o ${OUTPUT_DIR}/cf-mgmt-osx -ldflags "-X github.com/pivotal-michael-stergianis/cf-mgmt/configcommands.VERSION=${VERSION} -X github.com/pivotal-michael-stergianis/cf-mgmt/configcommands.COMMIT=${COMMIT}" cmd/cf-mgmt/main.go +GOOS=windows GOARCH=amd64 go build -o ${OUTPUT_DIR}/cf-mgmt.exe -ldflags "-X github.com/pivotal-michael-stergianis/cf-mgmt/configcommands.VERSION=${VERSION} -X github.com/pivotal-michael-stergianis/cf-mgmt/configcommands.COMMIT=${COMMIT}" cmd/cf-mgmt/main.go -CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ${OUTPUT_DIR}/cf-mgmt-config-linux -ldflags "-X github.com/pivotalservices/cf-mgmt/configcommands.VERSION=${VERSION} -X github.com/pivotalservices/cf-mgmt/configcommands.COMMIT=${COMMIT}" cmd/cf-mgmt-config/main.go -GOOS=darwin GOARCH=amd64 go build -o ${OUTPUT_DIR}/cf-mgmt-config-osx -ldflags "-X github.com/pivotalservices/cf-mgmt/configcommands.VERSION=${VERSION} -X github.com/pivotalservices/cf-mgmt/configcommands.COMMIT=${COMMIT}" cmd/cf-mgmt-config/main.go -GOOS=windows GOARCH=amd64 go build -o ${OUTPUT_DIR}/cf-mgmt-config.exe -ldflags "-X github.com/pivotalservices/cf-mgmt/configcommands.VERSION=${VERSION} -X github.com/pivotalservices/cf-mgmt/configcommands.COMMIT=${COMMIT}" cmd/cf-mgmt-config/main.go +CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ${OUTPUT_DIR}/cf-mgmt-config-linux -ldflags "-X github.com/pivotal-michael-stergianis/cf-mgmt/configcommands.VERSION=${VERSION} -X github.com/pivotal-michael-stergianis/cf-mgmt/configcommands.COMMIT=${COMMIT}" cmd/cf-mgmt-config/main.go +GOOS=darwin GOARCH=amd64 go build -o ${OUTPUT_DIR}/cf-mgmt-config-osx -ldflags "-X github.com/pivotal-michael-stergianis/cf-mgmt/configcommands.VERSION=${VERSION} -X github.com/pivotal-michael-stergianis/cf-mgmt/configcommands.COMMIT=${COMMIT}" cmd/cf-mgmt-config/main.go +GOOS=windows GOARCH=amd64 go build -o ${OUTPUT_DIR}/cf-mgmt-config.exe -ldflags "-X github.com/pivotal-michael-stergianis/cf-mgmt/configcommands.VERSION=${VERSION} -X github.com/pivotal-michael-stergianis/cf-mgmt/configcommands.COMMIT=${COMMIT}" cmd/cf-mgmt-config/main.go echo ${DRAFT_VERSION} > ${OUTPUT_DIR}/name echo ${DRAFT_VERSION} > ${OUTPUT_DIR}/tag diff --git a/ci/tasks/runTests.sh b/ci/tasks/runTests.sh index a4d15db4..76ca3f56 100755 --- a/ci/tasks/runTests.sh +++ b/ci/tasks/runTests.sh @@ -10,7 +10,7 @@ export PATH=$GOPATH/bin:$PATH mkdir -p $GOPATH/bin curl https://glide.sh/get | sh -WORKING_DIR=$GOPATH/src/github.com/pivotalservices/cf-mgmt +WORKING_DIR=$GOPATH/src/github.com/pivotal-michael-stergianis/cf-mgmt mkdir -p ${WORKING_DIR} cp -R source/* ${WORKING_DIR}/. cd ${WORKING_DIR} diff --git a/config/config.go b/config/config.go index 2f8c7295..9957ecd2 100644 --- a/config/config.go +++ b/config/config.go @@ -31,6 +31,10 @@ type Updater interface { CreateConfigIfNotExists(uaaOrigin string) error DeleteConfigIfExists() error + AssociateOrgAuditor(orgName, user string) error + AssociateSpaceDeveloper(orgName, spaceName, user string) error + AssociateSpaceAuditor(orgName, spaceName, user string) error + SaveOrgSpaces(spaces *Spaces) error SaveSpaceConfig(spaceConfig *SpaceConfig) error SaveOrgConfig(orgConfig *OrgConfig) error diff --git a/config/usermgmt.go b/config/usermgmt.go index 2fb4800a..791c34c6 100644 --- a/config/usermgmt.go +++ b/config/usermgmt.go @@ -27,3 +27,17 @@ func (u *UserMgmt) groups(groupName string) []string { } return result } + +func (u *UserMgmt) hasUAAUser(user string) bool { + for _, existentUser := range u.Users { + if user == existentUser { + return true + } + } + + return false +} + +func (u *UserMgmt) addUAAUser(user string) { + u.Users = append(u.Users, user) +} diff --git a/config/yaml_config.go b/config/yaml_config.go index c048fe39..90764ccc 100644 --- a/config/yaml_config.go +++ b/config/yaml_config.go @@ -647,3 +647,68 @@ func (m *yamlManager) SaveSpaceQuota(spaceQuota *SpaceQuota) error { fmt.Println(fmt.Sprintf("Saving Named Space Quote %s for org %s", spaceQuota.Name, spaceQuota.Org)) return WriteFile(targetFile, spaceQuota) } + +type userRole int + +const ( + auditorRole userRole = iota + developerRole +) + +func (m *yamlManager) AssociateOrgAuditor(orgName, user string) error { + orgConfig, err := m.GetOrgConfig(orgName) + if err != nil { + return err + } + + if orgConfig.Auditor.hasUAAUser(user) { + return nil + } + + // TODO: generalize so we can add users to correct origin + orgConfig.Auditor.addUAAUser(user) + if err = m.SaveOrgConfig(orgConfig); err != nil { + return err + } + + return nil +} + +func (m *yamlManager) AssociateSpaceAuditor(orgName, spaceName, user string) error { + return m.associateSpaceRole(auditorRole, orgName, spaceName, user) +} + +func (m *yamlManager) AssociateSpaceDeveloper(orgName, spaceName, user string) error { + return m.associateSpaceRole(developerRole, orgName, spaceName, user) +} + +func (m *yamlManager) associateSpaceRole(role userRole, orgName, spaceName, user string) error { + spaceConfig, err := m.GetSpaceConfig(orgName, spaceName) + if err != nil { + return err + } + + if spaceConfig.Developer.hasUAAUser(user) { + return nil + } + + var userManager *UserMgmt + switch role { + case auditorRole: + userManager = &spaceConfig.Auditor + case developerRole: + userManager = &spaceConfig.Developer + + // this cannot be tested as we cannot call unexported methods from the test package + default: + return errors.New("an invalid space role was provided") + } + + // TODO: generalize so we can add users to correct origin + userManager.addUAAUser(user) + if err = m.SaveSpaceConfig(spaceConfig); err != nil { + return err + } + + return nil +} diff --git a/config/yaml_config_test.go b/config/yaml_config_test.go index a78872ad..91697a2c 100644 --- a/config/yaml_config_test.go +++ b/config/yaml_config_test.go @@ -1,6 +1,7 @@ package config_test import ( + "fmt" "io/ioutil" "os" "path" @@ -476,4 +477,179 @@ var _ = Describe("CF-Mgmt Config", func() { }) }) + + Context("YAML Config Updater", func() { + Context("User Actions", func() { + var tempDir string + var configManager config.Manager + + BeforeEach(func() { + var err error + tempDir, err = ioutil.TempDir("", "cf-mgmt") + Expect(err).ShouldNot(HaveOccurred()) + configManager = config.NewManager(path.Join(tempDir, "cfmgmt")) + configManager.CreateConfigIfNotExists("ldap") + }) + + AfterEach(func() { + os.RemoveAll(tempDir) + }) + + Context("Associate Org Auditor", func() { + When("the org exists", func() { + const ( + orgName = "the-org" + userName = "the-user" + ) + BeforeEach(func() { + err := configManager.AddOrgToConfig(&config.OrgConfig{ + Org: orgName, + }) + Expect(err).ShouldNot(HaveOccurred()) + }) + + When("the user does not exist", func() { + It("adds the user to the org", func() { + o, err := configManager.GetOrgConfig(orgName) + Expect(err).ShouldNot(HaveOccurred()) + Expect(o.Auditor.Users).Should(HaveLen(0)) + + err = configManager.AssociateOrgAuditor(orgName, userName) + Expect(err).ShouldNot(HaveOccurred()) + + o, err = configManager.GetOrgConfig(orgName) + Expect(err).ShouldNot(HaveOccurred()) + Expect(o.Auditor.Users).Should(HaveLen(1)) + }) + }) + + When("the user already exists", func() { + BeforeEach(func() { + o, err := configManager.GetOrgConfig(orgName) + Expect(err).ShouldNot(HaveOccurred()) + + o.Auditor.Users = append(o.Auditor.Users, userName) + + err = configManager.SaveOrgConfig(o) + Expect(err).ShouldNot(HaveOccurred()) + }) + + It("does nothing and returns nil", func() { + o, err := configManager.GetOrgConfig(orgName) + Expect(err).ShouldNot(HaveOccurred()) + Expect(o.Auditor.Users).Should(HaveLen(1)) + + err = configManager.AssociateOrgAuditor(orgName, userName) + Expect(err).ShouldNot(HaveOccurred()) + + o, err = configManager.GetOrgConfig(orgName) + Expect(err).ShouldNot(HaveOccurred()) + Expect(o.Auditor.Users).Should(HaveLen(1)) + }) + }) + }) + + When("the org does not exist", func() { + It("returns an error", func() { + orgName := "org-that-does-not-exist" + err := configManager.AssociateOrgAuditor(orgName, "my-user") + Expect(err).Should(HaveOccurred()) + Expect(err).Should(MatchError(fmt.Sprintf("Org [%s] not found in config", orgName))) + }) + }) + }) + + Context("Associate Space Role", func() { + When("the org and space exist", func() { + const ( + orgName = "the-org" + spaceName = "the-space" + userName = "the-user" + ) + BeforeEach(func() { + err := configManager.AddOrgToConfig(&config.OrgConfig{ + Org: orgName, + }) + Expect(err).ShouldNot(HaveOccurred()) + + err = configManager.SaveOrgSpaces(&config.Spaces{ + Org: orgName, + }) + Expect(err).ShouldNot(HaveOccurred()) + + err = configManager.AddSpaceToConfig(&config.SpaceConfig{ + Org: orgName, + Space: spaceName, + }) + Expect(err).ShouldNot(HaveOccurred()) + }) + + When("the user does not exist in the space", func() { + It("creates the user with a developer role", func() { + s, err := configManager.GetSpaceConfig(orgName, spaceName) + Expect(err).ShouldNot(HaveOccurred()) + Expect(s.Developer.Users).Should(HaveLen(0)) + + err = configManager.AssociateSpaceDeveloper(orgName, spaceName, userName) + Expect(err).ShouldNot(HaveOccurred()) + + s, err = configManager.GetSpaceConfig(orgName, spaceName) + Expect(err).ShouldNot(HaveOccurred()) + Expect(s.Developer.Users).Should(HaveLen(1)) + }) + + It("creates the user with an auditor role", func() { + s, err := configManager.GetSpaceConfig(orgName, spaceName) + Expect(err).ShouldNot(HaveOccurred()) + Expect(s.Developer.Users).Should(HaveLen(0)) + + err = configManager.AssociateSpaceAuditor(orgName, spaceName, userName) + Expect(err).ShouldNot(HaveOccurred()) + + s, err = configManager.GetSpaceConfig(orgName, spaceName) + Expect(err).ShouldNot(HaveOccurred()) + Expect(s.Auditor.Users).Should(HaveLen(1)) + }) + }) + + When("user already exists in space", func() { + BeforeEach(func() { + s, err := configManager.GetSpaceConfig(orgName, spaceName) + Expect(err).ShouldNot(HaveOccurred()) + + s.Developer.Users = append(s.Developer.Users, userName) + + err = configManager.SaveSpaceConfig(s) + Expect(err).ShouldNot(HaveOccurred()) + }) + + It("does nothing and returns nil", func() { + s, err := configManager.GetSpaceConfig(orgName, spaceName) + Expect(err).ShouldNot(HaveOccurred()) + Expect(s.Developer.Users).Should(HaveLen(1)) + + err = configManager.AssociateSpaceDeveloper(orgName, spaceName, userName) + Expect(err).ShouldNot(HaveOccurred()) + + s, err = configManager.GetSpaceConfig(orgName, spaceName) + Expect(err).ShouldNot(HaveOccurred()) + Expect(s.Developer.Users).Should(HaveLen(1)) + }) + }) + }) + + When("the space cannot be found", func() { + It("returns an error", func() { + const ( + orgName = "org-that-maybe-exists" + spaceName = "space-that-does-not-exist" + ) + err := configManager.AssociateSpaceDeveloper(orgName, spaceName, "my-user") + Expect(err).Should(HaveOccurred()) + Expect(err).Should(MatchError(fmt.Sprintf("Space [%s] not found in org [%s] config", spaceName, orgName))) + }) + }) + }) + }) + }) }) diff --git a/glide.lock b/glide.lock index e0f60c00..c09bcfeb 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 39963338827c0b5242b4d1c86df8af7e7b63590d404c9c4d62f4781ac232b916 -updated: 2020-02-03T10:03:21.993149-07:00 +hash: cf9b6265466a608419984fc7218367f0dcee767efb4f883c86492993e74c2b15 +updated: 2020-02-18T11:38:24.451485-05:00 imports: - name: code.cloudfoundry.org/cfhttp version: 1f526aa7822e788b7e8b9dd097b0cf8c5b2fdb71 @@ -21,7 +21,7 @@ imports: version: 161a211c4903484706d816adaa367a7c9fcf9e3e repo: https://github.com/calebwashburn/go-cfclient - name: github.com/cloudfoundry-community/go-uaa - version: 10d9dedd9e3453da8bd404d938f4e1f52f12d589 + version: 673d775e96b5d67f107a28c169384df45dd9d0ac subpackages: - passwordcredentials - name: github.com/fatih/color @@ -36,10 +36,6 @@ imports: version: 96dc06278ce32a0e9d957d590bb987c81ee66407 - name: github.com/Masterminds/semver version: 3c560837130448941620d7694991d3ec440aefc0 -- name: github.com/mattn/go-colorable - version: efa589957cd060542a26d2dd7832fd6a6c6c3ade -- name: github.com/mattn/go-isatty - version: 3fb116b820352b7f0c281308a4d6250c22d94e27 - name: github.com/nu7hatch/gouuid version: 179d4d0c4d8d407a32af483c2354df1d2c91e6c3 - name: github.com/op/go-logging @@ -67,10 +63,6 @@ imports: subpackages: - clientcredentials - internal -- name: golang.org/x/sys - version: 1b2967e3c290b7c545b3db0deeda16e9be4f98a2 - subpackages: - - unix - name: google.golang.org/appengine version: b1f26356af11148e710935ed1ac8a7f5702c7612 subpackages: @@ -133,6 +125,10 @@ testImports: - matchers/support/goraph/node - matchers/support/goraph/util - types +- name: golang.org/x/sys + version: 1b2967e3c290b7c545b3db0deeda16e9be4f98a2 + subpackages: + - unix - name: golang.org/x/text version: 0605a8320aceb4207a5fb3521281e17ec2075476 subpackages: diff --git a/glide.yaml b/glide.yaml index 8541fddd..85fd1c43 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,4 +1,4 @@ -package: github.com/pivotalservices/cf-mgmt +package: github.com/pivotal-michael-stergianis/cf-mgmt import: - package: gopkg.in/yaml.v2 - package: github.com/xchapter7x/lo diff --git a/pipelines/sync-docker-image-to-internal.yml b/pipelines/sync-docker-image-to-internal.yml index 4e2375c5..dd66449b 100644 --- a/pipelines/sync-docker-image-to-internal.yml +++ b/pipelines/sync-docker-image-to-internal.yml @@ -3,7 +3,7 @@ resources: - name: docker-hub type: docker-image source: - repository: pivotalservices/cf-mgmt + repository: pivotal-michael-stergianis/cf-mgmt tag: latest - name: docker-registry type: docker-image diff --git a/uaa/users_test.go b/uaa/users_test.go index 7764c999..c5ec1625 100644 --- a/uaa/users_test.go +++ b/uaa/users_test.go @@ -1,7 +1,7 @@ package uaa_test import ( - . "github.com/pivotalservices/cf-mgmt/uaa" + . "github.com/pivotal-michael-stergianis/cf-mgmt/uaa" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega"