Skip to content
This repository has been archived by the owner on Feb 11, 2022. It is now read-only.

Commit

Permalink
Merge pull request #54 from mongodb/fix-statestorage
Browse files Browse the repository at this point in the history
  • Loading branch information
vasilevp authored Nov 13, 2020
2 parents cdd8c0d + 05de62c commit 042cf24
Show file tree
Hide file tree
Showing 20 changed files with 232 additions and 136 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy-broker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
uses: golangci/golangci-lint-action@v1
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.28
version: v1.32

# Optional: working directory, useful for monorepos
# working-directory:
Expand Down
21 changes: 18 additions & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,25 @@ linters:
- dogsled
- dupl
- errcheck
- errorlint
- exportloopref
- gochecknoinits
- gochecknoglobals
- gocritic
- gocyclo
- gofmt
- gofumpt
- goimports
- golint
- goprintffuncname
- gosec
- gosimple
- govet
- ineffassign
- interfacer
- misspell
- nlreturn
- nolintlint
- noctx
- prealloc
- rowserrcheck
- scopelint
- staticcheck
Expand All @@ -31,8 +36,18 @@ linters:
- unused
- varcheck
- whitespace
- wrapcheck
issues:
exclude-rules:
- path: test/
- path: test
linters:
- gocyclo
- gochecknoglobals
- wrapcheck
- nlreturn
- path: main.go
linters:
- gochecknoglobals
- wrapcheck
max-issues-per-linter: 0
max-same-issues: 0
1 change: 1 addition & 0 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,6 @@ func createFields(data []lager.Data) []interface{} {
fields = append(fields, k, v)
}
}

return fields
}
9 changes: 9 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,12 @@ func deduceCredentials(logger *zap.SugaredLogger, atlasURL string) *credentials.
switch {
case err == nil && creds == nil:
logger.Infow("Rejected Multi-Project (env): no credentials in env")

case err == nil:
logger.Info("Selected Multi-Project (env)")

return creds

default:
logger.Fatalw("Error while loading env credentials", "error", err)
}
Expand All @@ -120,15 +123,19 @@ func deduceCredentials(logger *zap.SugaredLogger, atlasURL string) *credentials.
switch {
case err == nil && creds == nil:
logger.Infow("Rejected Multi-Project (CredHub): not in CF")

case err == nil:
logger.Info("Selected Multi-Project (CredHub)")

return creds

default:
logger.Fatalw("Error while loading CredHub credentials", "error", err)
}

logger.Info("Selected Basic Auth")
logger.Fatal("Basic Auth credentials are not implemented yet")

return nil
}

Expand Down Expand Up @@ -196,6 +203,7 @@ func addSentryLogger(log *zap.Logger) *zap.Logger {
if err != nil {
log.Fatal("failed to init zap", zap.Error(err))
}

return zapsentry.AttachCoreToLogger(core, log)
}

Expand Down Expand Up @@ -227,5 +235,6 @@ func getBinaryFootprint() string {

cs := sha256.Sum256(f)
bcs := hex.EncodeToString(cs[:])

return bcs[:16]
}
3 changes: 3 additions & 0 deletions pkg/broker/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ func authMiddleware(auth credentials.BrokerAuth) mux.MiddlewareFunc {
username, password, ok := r.BasicAuth()
if !ok {
w.WriteHeader(http.StatusUnauthorized)

return
}

if auth.Username != username || auth.Password != password {
w.WriteHeader(http.StatusUnauthorized)

return
}

Expand Down Expand Up @@ -64,6 +66,7 @@ func simpleAuthMiddleware(baseURL string) mux.MiddlewareFunc {
validPassword := privKey != ""
if !(ok && validUsername && validPassword) {
w.WriteHeader(http.StatusUnauthorized)

return
}

Expand Down
16 changes: 13 additions & 3 deletions pkg/broker/binding_operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ import (
"crypto/rand"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"net/url"

"github.com/mongodb/atlas-osb/pkg/broker/dynamicplans"
"github.com/pivotal-cf/brokerapi/domain"
"github.com/pivotal-cf/brokerapi/domain/apiresponses"
"github.com/pkg/errors"
"go.mongodb.org/atlas/mongodbatlas"
)

Expand Down Expand Up @@ -70,6 +70,7 @@ func (b Broker) Bind(ctx context.Context, instanceID string, bindingID string, d
cluster, _, err := client.Clusters.Get(ctx, p.Project.ID, p.Cluster.Name)
if err != nil {
logger.Errorw("Failed to get existing cluster", "error", err)

return
}

Expand All @@ -78,19 +79,22 @@ func (b Broker) Bind(ctx context.Context, instanceID string, bindingID string, d
if err != nil {
logger.Errorw("Failed to generate password", "error", err)
err = errors.New("failed to generate binding password")

return
}

user, err := b.userFromParams(bindingID, password, details.RawParameters, p)
if err != nil {
logger.Errorw("Couldn't create user from the passed parameters", "error", err, "details", details)

return
}

// Create a new Atlas database user from the generated definition.
_, _, err = client.DatabaseUsers.Create(ctx, p.Project.ID, user)
if err != nil {
logger.Errorw("Failed to create Atlas database user", "error", err)

return
}

Expand All @@ -99,6 +103,7 @@ func (b Broker) Bind(ctx context.Context, instanceID string, bindingID string, d
cs, err := url.Parse(cluster.ConnectionStrings.StandardSrv)
if err != nil {
logger.Errorw("Failed to parse connection string", "error", err, "connString", cluster.ConnectionStrings.StandardSrv)

return
}

Expand All @@ -124,6 +129,7 @@ func (b Broker) Bind(ctx context.Context, instanceID string, bindingID string, d
spec = domain.Binding{
Credentials: connDetails,
}

return
}

Expand All @@ -142,19 +148,22 @@ func (b Broker) Unbind(ctx context.Context, instanceID string, bindingID string,
_, _, err = client.Clusters.Get(ctx, p.Project.ID, p.Cluster.Name)
if err != nil {
logger.Errorw("Failed to get existing cluster", "error", err)

return
}

// Delete database user which has the binding ID as its username.
_, err = client.DatabaseUsers.Delete(ctx, "admin", p.Project.ID, bindingID)
if err != nil {
logger.Errorw("Failed to delete Atlas database user", "error", err)

return
}

logger.Infow("Successfully deleted Atlas database user")

spec = domain.UnbindSpec{}

return
}

Expand All @@ -165,6 +174,7 @@ func (b Broker) GetBinding(ctx context.Context, instanceID string, bindingID str
logger.Infow("Retrieving binding")

err = apiresponses.NewFailureResponse(fmt.Errorf("unknown binding ID %s", bindingID), 404, "get-binding")

return
}

Expand All @@ -182,7 +192,7 @@ func generatePassword() (string, error) {

_, err := rand.Read(b)
if err != nil {
return "", err
return "", errors.Wrap(err, "cannot read random bytes")
}

return base64.URLEncoding.EncodeToString(b), nil
Expand All @@ -201,7 +211,7 @@ func (b *Broker) userFromParams(bindingID string, password string, rawParams []b
if len(rawParams) > 0 {
err := json.Unmarshal(rawParams, &params)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "cannot unmarshal raw parameters")
}
}

Expand Down
27 changes: 21 additions & 6 deletions pkg/broker/broker.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func New(
}

b.buildCatalog()

return b
}

Expand All @@ -91,6 +92,7 @@ func (b *Broker) funcLogger() *zap.SugaredLogger {
frames := runtime.CallersFrames(pc)
f, _ := frames.Next()
split := strings.Split(f.Function, ".")

return b.logger.With("func", split[len(split)-1])
}

Expand All @@ -99,12 +101,14 @@ func (b *Broker) parsePlan(ctx dynamicplans.Context, planID string) (dp *dynamic
sp, ok := b.catalog.plans[planID]
if !ok {
err = fmt.Errorf("plan ID %q not found in catalog", planID)

return
}

tpl, ok := sp.Metadata.AdditionalMetadata["template"].(dynamicplans.TemplateContainer)
if !ok {
err = fmt.Errorf("plan ID %q does not contain a valid plan template", planID)

return
}

Expand Down Expand Up @@ -146,6 +150,7 @@ func (b *Broker) getInstancePlan(ctx context.Context, instanceID string) (*dynam
}

plan, err := decodePlan(params)

return &plan, err
}

Expand All @@ -158,6 +163,7 @@ func (b *Broker) getPlan(ctx context.Context, instanceID string, planID string,
// planCtx == nil means the instance should exist
if planCtx == nil {
err = errors.Wrapf(err, "cannot find plan for instance %q", instanceID)

return
}

Expand All @@ -169,6 +175,7 @@ func (b *Broker) getPlan(ctx context.Context, instanceID string, planID string,

if dp.Project == nil {
err = fmt.Errorf("missing Project in plan definition")

return
}

Expand Down Expand Up @@ -196,18 +203,21 @@ func (b *Broker) getClient(ctx context.Context, instanceID string, planID string

default:
err = errors.New("template must contain either APIKey or Project.OrgID")

return
}

hc, err := digest.NewTransport(key.PublicKey, key.PrivateKey).Client()
if err != nil {
err = errors.Wrap(err, "cannot create Digest client")

return
}

client, err = mongodbatlas.New(hc, mongodbatlas.SetBaseURL(b.cfg.AtlasURL))
if err != nil {
err = errors.Wrap(err, "cannot create Atlas client")

return
}

Expand All @@ -216,20 +226,22 @@ func (b *Broker) getClient(ctx context.Context, instanceID string, planID string
existing, _, err = client.Projects.GetOneProjectByName(ctx, dp.Project.Name)
if err == nil {
dp.Project = existing

return
}

err = nil

return
}

func (b *Broker) getState(orgID string) (*statestorage.RealmStateStorage, error) {
func (b *Broker) getState(ctx context.Context, orgID string) (*statestorage.RealmStateStorage, error) {
key, err := b.credentials.ByOrg(orgID)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "cannot get API Key by org")
}

return statestorage.Get(key, b.cfg.AtlasURL, b.cfg.RealmURL, b.logger)
return statestorage.Get(ctx, key, b.cfg.AtlasURL, b.cfg.RealmURL, b.logger)
}

func (b *Broker) AuthMiddleware() mux.MiddlewareFunc {
Expand All @@ -246,6 +258,7 @@ func (b *Broker) GetDashboardURL(groupID, clusterName string) string {
return err.Error()
}
apiURL.Path = fmt.Sprintf("/v2/%s", groupID)

return apiURL.String() + fmt.Sprintf("#clusters/detail/%s", clusterName)
}

Expand All @@ -254,16 +267,18 @@ func encodePlan(v dynamicplans.Plan) (string, error) {
b64 := base64.NewEncoder(base64.StdEncoding, b)
err := json.NewEncoder(b64).Encode(v)
if err != nil {
return "", err
return "", errors.Wrap(err, "cannot marshal plan")
}

err = b64.Close()
return b.String(), err

return b.String(), errors.Wrap(err, "cannot finalize base64")
}

func decodePlan(enc string) (dynamicplans.Plan, error) {
b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(enc))
dp := dynamicplans.Plan{}
err := json.NewDecoder(b64).Decode(&dp)
return dp, err

return dp, errors.Wrap(err, "cannot unmarshal plan")
}
Loading

0 comments on commit 042cf24

Please sign in to comment.