Fix livestatereporter to consider multiple plugins in one app#5457
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
| // 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.
it's not a single plugin which deploys an application but it's a list of plugins do
c1654db to
0c4fc0d
Compare
|
@ffjlabo go lint error found, please fix it |
|
@khanhtc1202 Fixed for the lint |
|
📝 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.
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.
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
| // 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.
We need it to show livestates by grouping with plugin
Signed-off-by: Yoshiki Fujikane <ffjlabo@gmail.com>
Signed-off-by: Yoshiki Fujikane <ffjlabo@gmail.com>
Signed-off-by: Yoshiki Fujikane <ffjlabo@gmail.com>
Signed-off-by: Yoshiki Fujikane <ffjlabo@gmail.com>
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.
Looks like we don't use this 👀
Signed-off-by: Yoshiki Fujikane <ffjlabo@gmail.com>
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.
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.
| case <-snapshotTicker.C: | ||
| pr.flushSnapshots(ctx) | ||
| eg, ctx := errgroup.WithContext(ctx) | ||
| eg.SetLimit(limit) |
There was a problem hiding this comment.
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.
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.
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.
Sorry, I forgot to save the file. Added it
c7df424
There was a problem hiding this comment.
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.
Signed-off-by: Yoshiki Fujikane <ffjlabo@gmail.com>
Signed-off-by: Yoshiki Fujikane <ffjlabo@gmail.com>
Signed-off-by: Yoshiki Fujikane <ffjlabo@gmail.com>
Warashi
left a comment
There was a problem hiding this comment.
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.
There is no use of b *testing.B; what is this benchmark to measure?
There was a problem hiding this comment.
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.
Okay, I got it.
Then you should use testing.B as below.
for range b.N {
pr.flushSnapshots(context.Background())
}| logger: zaptest.NewLogger(t), | ||
| } | ||
|
|
||
| pr.flushSnapshots(context.Background()) |
There was a problem hiding this comment.
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.
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 <ffjlabo@gmail.com>
Signed-off-by: Yoshiki Fujikane <ffjlabo@gmail.com>

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_sourcetoGetLivestateRequest.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?: