-
Notifications
You must be signed in to change notification settings - Fork 157
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
Fix livestatereporter to consider multiple plugins in one app #5457
Conversation
fa22a0f
to
a6603eb
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #5457 +/- ##
==========================================
+ Coverage 26.29% 26.62% +0.33%
==========================================
Files 464 464
Lines 49626 49737 +111
==========================================
+ Hits 13047 13241 +194
+ Misses 35546 35437 -109
- Partials 1033 1059 +26 ☔ View full report in Codecov by Sentry. |
pkg/model/application.proto
Outdated
@@ -45,6 +45,8 @@ message Application { | |||
string platform_provider = 15; | |||
// The names of deploy taget where to deploy this application. | |||
repeated string deploy_targets = 16; | |||
// The name of plugin used to deploy this application. | |||
string plugin = 17; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not a single plugin which deploys an application but it's a list of plugins do
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@khanhtc1202
Thanks, fixed it on 0c4fc0d
c1654db
to
0c4fc0d
Compare
@ffjlabo go lint error found, please fix it |
@khanhtc1202 Fixed for the lint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
📝 We decided to determine the plugin used on the application from app.pipecd.yaml. So I will fix not to add plugin name to the application model. |
0e3e607
to
cd2b7f1
Compare
// TODO: Set the limit based on the piped config | ||
limit := runtime.GOMAXPROCS(0) / 2 | ||
|
||
// Report the application live state to the control plane. | ||
snapshot := &model.ApplicationLiveStateSnapshot{ | ||
ApplicationId: app.Id, | ||
PipedId: app.PipedId, | ||
ProjectId: app.ProjectId, | ||
Kind: app.Kind, | ||
ApplicationLiveState: res.GetApplicationLiveState(), | ||
appsPerReporter := len(apps) / limit | ||
if appsPerReporter == 0 { | ||
appsPerReporter = 1 | ||
} | ||
|
||
appsGrouped := make([][]*model.Application, 0) | ||
for i := 0; i < len(apps); i += appsPerReporter { | ||
end := i + appsPerReporter | ||
if end > len(apps) { | ||
end = len(apps) | ||
} | ||
snapshot.DetermineApplicationHealthStatus() | ||
|
||
if _, err := pr.apiClient.ReportApplicationLiveState(ctx, &pipedservice.ReportApplicationLiveStateRequest{ | ||
Snapshot: snapshot, | ||
}); err != nil { | ||
pr.logger.Error("failed to report application live state", | ||
zap.String("application-id", app.Id), | ||
zap.Error(err), | ||
) | ||
appsGrouped = append(appsGrouped, apps[i:end]) | ||
} | ||
|
||
eg, ctx := errgroup.WithContext(ctx) | ||
eg.SetLimit(limit) | ||
|
||
r.logger.Info("start flushing snapshots", zap.Int("application-count", len(apps)), zap.Int("concurrency", limit)) | ||
for _, apps := range appsGrouped { | ||
eg.Go(func() error { | ||
r.flushAll(ctx, apps, repoMap) | ||
return nil | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At first, I tried to implement the livestate reporter to process the apps grouped by plugins because the livestatereporter for pipedv0 processes the apps grouped by platform providers.
But it finds the plugin name of the app based on the app config.
It takes some more time and resource to prepare the deploy sources for all of the apps in one time.
So I implemented it in paralell.
dir, err := os.MkdirTemp(r.workingDir, fmt.Sprintf("app-%s-*", app.Id)) | ||
if err != nil { | ||
r.logger.Error("failed to create temporary directory", zap.Error(err)) | ||
return err | ||
} | ||
|
||
dsp := deploysource.NewProvider(dir, deploysource.NewLocalSourceCloner(repo, "target", "HEAD"), app.GitPath, r.secretDecrypter) | ||
ds, err := dsp.Get(ctx, io.Discard) | ||
if err != nil { | ||
r.logger.Error("failed to get deploy source", zap.String("application-id", app.Id), zap.Error(err)) | ||
return err | ||
} | ||
|
||
cfg, err := config.DecodeYAML[*config.GenericApplicationSpec](ds.ApplicationConfig) | ||
if err != nil { | ||
r.logger.Error("unable to parse application config", zap.Error(err)) | ||
return err | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use the Deploy Source for two reasons.
- to use app.pipecd.yaml for the app
- to pass it when calling
GetLivestate
. It expects to use it do do drift detection.
08a4aa9
to
c951ab9
Compare
@@ -108,6 +108,8 @@ message ResourceState { | |||
string health_description = 7; | |||
// The target where this resource is deployed. | |||
string deploy_target = 8; | |||
// The plugin name that manages this resource. | |||
string plugin_name = 9; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need it to show livestates by grouping with plugin
Signed-off-by: Yoshiki Fujikane <[email protected]>
Signed-off-by: Yoshiki Fujikane <[email protected]>
Signed-off-by: Yoshiki Fujikane <[email protected]>
Signed-off-by: Yoshiki Fujikane <[email protected]>
Signed-off-by: Yoshiki Fujikane <[email protected]>
Signed-off-by: Yoshiki Fujikane <[email protected]>
e40079e
to
d14e25d
Compare
option go_package = "github.com/pipe-cd/pipecd/pkg/plugin/api/v1alpha1/common"; | ||
|
||
import "validate/validate.proto"; | ||
import "pkg/model/common.proto"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we don't use this 👀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, removed them
Signed-off-by: Yoshiki Fujikane <[email protected]>
d14e25d
to
11a9a14
Compare
logger *zap.Logger | ||
} | ||
// TODO: Set the limit based on the piped config | ||
limit := runtime.GOMAXPROCS(0) / 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When runtime.GOMAXPROCS(0)
returns 1
, limit
becomes 0
.
This causes the division-by-zero error.
Please set the limit 1
if it is 0
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, fixed on 5ea0571
case <-snapshotTicker.C: | ||
pr.flushSnapshots(ctx) | ||
eg, ctx := errgroup.WithContext(ctx) | ||
eg.SetLimit(limit) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use the appsGrouped
to limit concurrency, so we don't need this SetLimit.
Or, we can use only eg.SetLimit
and simply call eg.Go
with all apps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, you're right. Also there is no reason to use errgroup, so I fixed to use wait group instead of it.
af57c01
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
syntax = "proto3"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about adding comments on where to use this package?
I imagine this common package to be used in the deployment/livestate package as a dependency, and I want to clarify it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I forgot to save the file. Added it
c7df424
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about this long comment?
"// package common defines common messages which are depended on by messages in packages under pkg/plugin/api/v1alpha1."
As Sawada-san mentioned, I want to clarify what common
means because common
package will be also visible to plugin developers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, fixed it.
c5284f3
Signed-off-by: Yoshiki Fujikane <[email protected]>
Signed-off-by: Yoshiki Fujikane <[email protected]>
Signed-off-by: Yoshiki Fujikane <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I forgot to review the test codes.
I commented on it.
logger: zaptest.NewLogger(b), | ||
} | ||
|
||
pr.flushSnapshots(context.Background()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no use of b *testing.B
; what is this benchmark to measure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to measure the time to execute it in parallel for reference.
I left it because It will be helpful to check the performance. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I got it.
Then you should use testing.B as below.
for range b.N {
pr.flushSnapshots(context.Background())
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I added it.
3adea7e
logger: zaptest.NewLogger(t), | ||
} | ||
|
||
pr.flushSnapshots(context.Background()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are no assertion statements.
Does this test only assert that no panic occurred? If so, it's better to comment on that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I added a comment and a new test for flush
to check the logic. (currently added only the success case)
8b8f4c6
Signed-off-by: Yoshiki Fujikane <[email protected]>
Signed-off-by: Yoshiki Fujikane <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Signed-off-by: Yoshiki Fujikane <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
What this PR does:
Fix to start the livestatereporter when starting pipedv1.Also, I added a plugin name field for the application model to list apps by it.I fixed the livestatereporter to consider the multiple plugins situation.
Modify to use DeploySource
deploy_source
toGetLivestateRequest
.Modify to merge Livestate
LivestateState
SyncState
Note: the current Web UI for each field above.

Why we need it:
These fixes are needed to start the internal reporter for each plugin.Since multiple plugins will be supported for one app, each plugin will be able to support its own Livestate.
Therefore, I retrieved all the Livestates and merged the results to display them.
Which issue(s) this PR fixes:
Part of #5363
Does this PR introduce a user-facing change?: