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

Add mongodb client #653

Merged
merged 6 commits into from
Aug 24, 2020
Merged

Add mongodb client #653

merged 6 commits into from
Aug 24, 2020

Conversation

nakabonne
Copy link
Member

What this PR does / why we need it:
With this PR, MongoDB will be available only on a standalone server as a datastore for control-plane.

Which issue(s) this PR fixes:

Fixes #37

Does this PR introduce a user-facing change?:

NONE

pkg/datastore/mongodb/mongodb.go Show resolved Hide resolved
func (a *Application) MarshalBSON() ([]byte, error) {
// TODO: Replace "fatih/structs" with "mitchellh/mapstructure"
// Currently using fatih/structs temporarily to easily convert all nested structures into a map.
m := structs.Map(a)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the nested structs can be converted to maps. So keys are ensured to be camel case like:

{ "_id" : "abc123", "Name" : "foo", "ProjectId" : "proj-id", "CloudProvider" : "provider", "CreatedAt" : NumberLong(1), "UpdatedAt" : NumberLong(1), "EnvId" : "env-id", "MostRecentlySuccessfulDeployment" : null, "Kind" : 0, "MostRecentlyTriggeredDeployment" : null, "SyncState" : { "Status" : 1, "ShortReason" : "", "Reason" : "", "HeadDeploymentId" : "", "Timestamp" : NumberLong(1) }, "Disabled" : false, "PipedId" : "piped-id", "GitPath" : { "ConfigPath" : "", "ConfigFilename" : "", "Url" : "", "Repo" : { "Id" : "id", "Remote" : "", "Branch" : "" }, "Path" : "path" } }

@nakabonne
Copy link
Member Author

/cc @stormcat24 @nghialv

@pipecd-bot
Copy link
Collaborator

COVERAGE

Code coverage for golang is 20.85%. This pull request decreases coverage by -0.22%.

File Function Base Head Diff
pkg/model/bson.go Application.MarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Application.UnmarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Command.MarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Command.UnmarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Deployment.MarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Deployment.UnmarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Environment.MarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Environment.UnmarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Piped.MarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Piped.UnmarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Project.MarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Project.UnmarshalBSON -- 0.00% +0.00%
pkg/app/api/service/webservice/client.go NewClient 0.00% 0.00% +0.00%

@pipecd-bot
Copy link
Collaborator

COVERAGE

Code coverage for golang is 20.85%. This pull request decreases coverage by -0.22%.

File Function Base Head Diff
pkg/model/bson.go Application.MarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Application.UnmarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Command.MarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Command.UnmarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Deployment.MarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Deployment.UnmarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Environment.MarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Environment.UnmarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Piped.MarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Piped.UnmarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Project.MarshalBSON -- 0.00% +0.00%
pkg/model/bson.go Project.UnmarshalBSON -- 0.00% +0.00%
pkg/app/api/service/webservice/client.go NewClient 0.00% 0.00% +0.00%

pkg/model/bson.go Outdated Show resolved Hide resolved
pkg/config/control_plane.go Show resolved Hide resolved
pkg/datastore/mongodb/mongodb.go Show resolved Hide resolved
pkg/datastore/mongodb/mongodb.go Outdated Show resolved Hide resolved
pkg/datastore/mongodb/mongodb.go Outdated Show resolved Hide resolved
@nakabonne
Copy link
Member Author

I've tested all of methods of *mongodb.MongoDB works as expected with simple e2e tests.
However, it may be ended with failure in corner cases. After deploying, I'm going to do more authentic tests.

pkg/datastore/mongodb/mongodb.go Show resolved Hide resolved
pkg/datastore/mongodb/mongodb.go Outdated Show resolved Hide resolved

func NewMongoDB(ctx context.Context, url, database string, opts ...Option) (*MongoDB, error) {
// TODO: Enable to specify username and password via file.
// Need to check if it overrides AuthMechanism etc.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a question, why the second line has a different indent? The TODO plugin will do something for us?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for letting you get confused. This is for IntelliJ IDEA. Making indent, then IDEA can recognize they are part of TODO comment and highlights:
image

pkg/datastore/mongodb/operator.go Outdated Show resolved Hide resolved
m[mongodbPrimaryKey] = a.Id
delete(m, "Id")

return bson.Marshal(m)
Copy link
Member

@nghialv nghialv Aug 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this way, we cost 2 times for converting the model to the map and marshaling the map.
How about using a wrapper struct to minimize the cost.

type IDGetter interface {
   GetID() string
}

type MongoDBModelWrapper struct {
    IDGetter               `bson:",inline"`
    ID objectid.ObjectID   `bson:"_id"`
}

// The IDGetter can be any model: Application, Deployment, ...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm looking into that way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although this way causes adding both _id and id fields inside the DB, I think that is fine.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been considering that.

@nakabonne
Copy link
Member Author

Unmarshaling bson requires a concrete type, that's why I determined to use concrete type structs, not interfaces suggested at #653 (comment)

@pipecd-bot
Copy link
Collaborator

COVERAGE

Code coverage for golang is 21.07%. This pull request decreases coverage by -0.00%.

File Function Base Head Diff
pkg/app/api/service/webservice/client.go NewClient 0.00% 0.00% +0.00%

@@ -0,0 +1,186 @@
// Copyright 2020 The PipeCD Authors.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking about moving the wrapper implementation to a new mongodb/wrapper package.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of them are private models and functions so I think it is fine to place them inside this package.

setID(id string)
// storeModel stores the unwrapped model in the value pointed to by v.
storeModel(v interface{}) error
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because eventually, we have to define all of the wrappers (application, command...) in this package so just want to simplify this part.

func wrapModel(entity interface{}) (interface{}, error) {
    switch e := entity.(type) {
        case *model.Application:
            return *application{Application: e, ID: e.Id}, nil
         ....
         default:
            return nil, fmt.Errorf("%T is not supported", e)
    }
}

func extractModel(w interface{}, e interface{}) error {
     switch w:= w.(type) {
          case *application:
                *e = w.Application
          ...
          default:
               return nil, fmt.Errorf("%T is not supported", e)
	}
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with your idea, gonna apply it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... actually we need setID method for updating. MongoDB doesn't allow empty "_id" when updating.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why do need that setID method. The _id value was already set in the wrapModel function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, take a look at the behavior of updating. The given entity doesn't have Id, so the generated wrapper has no way to know its id.
https://github.com/pipe-cd/pipe/pull/653/files/bb7bc703dbd015ab851faee9501d86797b160e08#diff-825491436922437713c5651bc145ccd8R189-R212

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hold on, id shoud be populated when decoding.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll check it again.

@pipecd-bot
Copy link
Collaborator

TODO

The following ISSUES will be created once got merged. If you want me to skip creating the issue, you can use /todo skip command.

Details

1. Enable to specify username and password via file.

https://github.com/pipe-cd/pipe/blob/1dc024cb30a4d8c557755b98b9693d6e5602d044/pkg/datastore/mongodb/mongodb.go#L39-L42

This was created by todo plugin since "TODO:" was found in 1dc024c when #653 was merged. cc: @nakabonne.

2. Support updating process with using transaction on mongoDB cluster

https://github.com/pipe-cd/pipe/blob/1dc024cb30a4d8c557755b98b9693d6e5602d044/pkg/datastore/mongodb/mongodb.go#L140-L143

This was created by todo plugin since "TODO:" was found in 1dc024c when #653 was merged. cc: @nakabonne.

@nakabonne
Copy link
Member Author

Applied 👍

@nghialv
Copy link
Member

nghialv commented Aug 24, 2020

Good Job!
/approve

@pipecd-bot
Copy link
Collaborator

APPROVE

This pull request is APPROVED by nghialv.

Approvers can cancel the approval by writing /approve cancel in a comment. Any additional commits also will change this pull request to be not-approved.

@nakabonne
Copy link
Member Author

Thank you for your deep review.

@pipecd-bot
Copy link
Collaborator

TEMPLATE

failed to handle template rule examples

Details
Error: unabled to push rendered files to destination

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add datastore client for MongoDB
4 participants