Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
7d95dc2
Rename file referring to other platforms
t-kikuc May 3, 2024
590e649
Add ECS to live-state protobuf
t-kikuc May 3, 2024
b1a4e6e
Impl ECS APIs
t-kikuc May 4, 2024
31cdabe
Impl ECS's state.go
t-kikuc May 4, 2024
cda4764
Fix the healthDescription because a task has two statuses
t-kikuc May 4, 2024
8f65a95
Add GetClusterTasks func
t-kikuc May 5, 2024
44931c8
draft: add ecs store.go
t-kikuc May 7, 2024
40c4333
Add ECSApplicationLiveState to ApplicationLiveStateSnapshot and gen code
t-kikuc Jun 10, 2024
85c2618
Fix typo: ECSRun -> ECS
t-kikuc Jun 10, 2024
23fde0d
draft: reporter, model
t-kikuc Jun 10, 2024
11ec154
remove applicationLister from ECS
t-kikuc Jun 12, 2024
22c3152
Define blank funcs in Getter
t-kikuc Jun 12, 2024
8d6cecd
impl NewStore, GetManifests, GetState, WaitForReady
t-kikuc Jun 12, 2024
cbac8ed
Add GetTaskDefinition()
t-kikuc Jun 13, 2024
842915c
fix comment
t-kikuc Jun 13, 2024
9304b16
Revert "Add GetTaskDefinition()"
t-kikuc Jun 13, 2024
2feb9ec
Revert "Revert "Add GetTaskDefinition()""
t-kikuc Jun 13, 2024
6dbaa71
impl store.go
t-kikuc Jun 13, 2024
a30e1fb
Impl ecs.go > Run()
t-kikuc Jun 13, 2024
934950c
impl ecs/report.go]
t-kikuc Jun 13, 2024
04f364b
add switch case of ECS
t-kikuc Jun 13, 2024
66fd1dd
fix livestatestore v1 for ecs
t-kikuc Jun 13, 2024
eb92e76
Add ecs/state_test.go
t-kikuc Jun 14, 2024
a43ee22
fix comments
t-kikuc Jun 14, 2024
c299405
remove comment
t-kikuc Jun 14, 2024
0622690
Remove TODO comment
t-kikuc Jun 14, 2024
1007be3
Remove standalone tasks states
t-kikuc Jun 14, 2024
53c5971
fix fetching ecs resources
t-kikuc Jun 17, 2024
c3e9e5f
Fix appId key in store: use appId tag
t-kikuc Jun 18, 2024
e6b1ee6
Remove validation of ApiVersion of ECS
t-kikuc Jun 18, 2024
516d5bd
Merge branch 'master' of https://github.com/pipe-cd/pipecd into ecs-l…
t-kikuc Jun 18, 2024
bc8eb77
Fix updatedAt of ECS Service to pass validation
t-kikuc Jun 18, 2024
18c048c
Use VersionV1Beta1 for ECS states
t-kikuc Jun 18, 2024
facbff2
Revert "Remove validation of ApiVersion of ECS"
t-kikuc Jun 18, 2024
730460d
Fix comments
t-kikuc Jun 18, 2024
7c0ab99
fix pipedv1
t-kikuc Jun 19, 2024
ac5ade7
fix test: add apiversion, updatedat
t-kikuc Jun 19, 2024
0cab4c7
remove comment-outed namespace
t-kikuc Jun 19, 2024
01a5abf
Merge branch 'master' into ecs-live-state-store
t-kikuc Jun 26, 2024
b869b70
Use ID for ResourceState of taskset and task
t-kikuc Jun 27, 2024
3adaa79
Merge branch 'ecs-live-state-store' of https://github.com/pipe-cd/pip…
t-kikuc Jun 27, 2024
29113ae
Fix nits: arrange import section
t-kikuc Jul 2, 2024
2d92252
Merge branch 'master' into ecs-live-state-store
t-kikuc Jul 4, 2024
93edc0d
Remove ApiVersion & Namespace from ECSResourceState
t-kikuc Jul 16, 2024
865df89
Merge branch 'ecs-live-state-store' of https://github.com/pipe-cd/pip…
t-kikuc Jul 16, 2024
eb96de8
add test cases for ECS in DetermineAppHealthStatus
t-kikuc Jul 16, 2024
8f376e5
Merge branch 'master' into ecs-live-state-store
t-kikuc Jul 22, 2024
0e87b36
fix indents
t-kikuc Jul 22, 2024
464b442
fix indent
t-kikuc Jul 22, 2024
0f44577
fix indent
t-kikuc Jul 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions pkg/app/piped/livestatereporter/ecs/report.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Copyright 2024 The PipeCD Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ecs

import (
"context"
"fmt"
"time"

"github.com/pipe-cd/pipecd/pkg/app/piped/livestatestore/ecs"
"github.com/pipe-cd/pipecd/pkg/app/server/service/pipedservice"
"github.com/pipe-cd/pipecd/pkg/config"
"github.com/pipe-cd/pipecd/pkg/model"
"go.uber.org/zap"
"google.golang.org/grpc"
)

type applicationLister interface {
ListByPlatformProvider(name string) []*model.Application
}

type apiClient interface {
ReportApplicationLiveState(ctx context.Context, req *pipedservice.ReportApplicationLiveStateRequest, opts ...grpc.CallOption) (*pipedservice.ReportApplicationLiveStateResponse, error)
ReportApplicationLiveStateEvents(ctx context.Context, req *pipedservice.ReportApplicationLiveStateEventsRequest, opts ...grpc.CallOption) (*pipedservice.ReportApplicationLiveStateEventsResponse, error)
}

type Reporter interface {
Run(ctx context.Context) error
ProviderName() string
}

type reporter struct {
provider config.PipedPlatformProvider
appLister applicationLister
stateGetter ecs.Getter
apiClient apiClient
snapshotFlushInterval time.Duration
logger *zap.Logger

snapshotVersions map[string]model.ApplicationLiveStateVersion
}

func NewReporter(cp config.PipedPlatformProvider, appLister applicationLister, stateGetter ecs.Getter, apiClient apiClient, logger *zap.Logger) Reporter {
logger = logger.Named("ecs-reporter").With(
zap.String("platform-provider", cp.Name),
)
return &reporter{
provider: cp,
appLister: appLister,
stateGetter: stateGetter,
apiClient: apiClient,
snapshotFlushInterval: time.Minute,
logger: logger,
snapshotVersions: make(map[string]model.ApplicationLiveStateVersion),
}
}

func (r *reporter) Run(ctx context.Context) error {
r.logger.Info("start running app live state reporter")

r.logger.Info("waiting for livestatestore to be ready")
if err := r.stateGetter.WaitForReady(ctx, 10*time.Minute); err != nil {
r.logger.Error("livestatestore was unable to be ready in time", zap.Error(err))
return err
}

snapshotTicker := time.NewTicker(r.snapshotFlushInterval)
defer snapshotTicker.Stop()

for {
select {
case <-snapshotTicker.C:
r.flushSnapshots(ctx)

case <-ctx.Done():
r.logger.Info("app live state reporter has been stopped")
return nil
}
}
}

func (r *reporter) ProviderName() string {
return r.provider.Name
}

func (r *reporter) flushSnapshots(ctx context.Context) {
apps := r.appLister.ListByPlatformProvider(r.provider.Name)
for _, app := range apps {
state, ok := r.stateGetter.GetState(app.Id)
if !ok {
r.logger.Info(fmt.Sprintf("no app state of ecs application %s to report", app.Id))
continue
}

snapshot := &model.ApplicationLiveStateSnapshot{
ApplicationId: app.Id,
PipedId: app.PipedId,
ProjectId: app.ProjectId,
Kind: app.Kind,
Ecs: &model.ECSApplicationLiveState{
Resources: state.Resources,
},
Version: &state.Version,
}
snapshot.DetermineAppHealthStatus()
req := &pipedservice.ReportApplicationLiveStateRequest{
Snapshot: snapshot,
}

if _, err := r.apiClient.ReportApplicationLiveState(ctx, req); err != nil {
r.logger.Error("failed to report application live state",
zap.String("application-id", app.Id),
zap.Error(err),
)
continue
}
r.snapshotVersions[app.Id] = state.Version
r.logger.Info(fmt.Sprintf("successfully reported application live state for application: %s", app.Id))
}
}
8 changes: 8 additions & 0 deletions pkg/app/piped/livestatereporter/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"google.golang.org/grpc"

"github.com/pipe-cd/pipecd/pkg/app/piped/livestatereporter/cloudrun"
"github.com/pipe-cd/pipecd/pkg/app/piped/livestatereporter/ecs"
"github.com/pipe-cd/pipecd/pkg/app/piped/livestatereporter/kubernetes"
"github.com/pipe-cd/pipecd/pkg/app/piped/livestatestore"
"github.com/pipe-cd/pipecd/pkg/app/server/service/pipedservice"
Expand Down Expand Up @@ -79,6 +80,13 @@ func NewReporter(appLister applicationLister, stateGetter livestatestore.Getter,
continue
}
r.reporters = append(r.reporters, cloudrun.NewReporter(cp, appLister, sg, apiClient, logger))
case model.PlatformProviderECS:
sg, ok := stateGetter.ECSGetter(cp.Name)
if !ok {
r.logger.Error(fmt.Sprintf(errFmt, cp.Name))
continue
}
r.reporters = append(r.reporters, ecs.NewReporter(cp, appLister, sg, apiClient, logger))
}
}

Expand Down
118 changes: 118 additions & 0 deletions pkg/app/piped/livestatestore/ecs/ecs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright 2024 The PipeCD Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ecs

import (
"context"
"time"

"go.uber.org/zap"

provider "github.com/pipe-cd/pipecd/pkg/app/piped/platformprovider/ecs"
"github.com/pipe-cd/pipecd/pkg/config"
"github.com/pipe-cd/pipecd/pkg/model"
)

type Store struct {
store *store
logger *zap.Logger
interval time.Duration
firstSyncedCh chan error
}

type Getter interface {
GetECSManifests(appID string) (provider.ECSManifests, bool)
GetState(appID string) (State, bool)

WaitForReady(ctx context.Context, timeout time.Duration) error
}

type State struct {
Resources []*model.ECSResourceState
Version model.ApplicationLiveStateVersion
}

func NewStore(cfg *config.PlatformProviderECSConfig, platformProvider string, logger *zap.Logger) (*Store, error) {
logger = logger.Named("ecs").
With(zap.String("platform-provider", platformProvider))

client, err := provider.DefaultRegistry().Client(platformProvider, cfg, logger)
if err != nil {
return nil, err
}

store := &Store{
store: &store{
client: client,
logger: logger.Named("store"),
},
interval: 15 * time.Second,
logger: logger,
firstSyncedCh: make(chan error, 1),
}

return store, nil
}

func (s *Store) Run(ctx context.Context) error {
s.logger.Info("start running ecs app state store")

tick := time.NewTicker(s.interval)
defer tick.Stop()

// Run the first sync of ECS resources.
if err := s.store.run(ctx); err != nil {
s.firstSyncedCh <- err
return err
}

s.logger.Info("successfully ran the first sync of all ecs resources")
close(s.firstSyncedCh)

for {
select {
case <-ctx.Done():
s.logger.Info("ecs app state store has been stopped")
return nil

case <-tick.C:
if err := s.store.run(ctx); err != nil {
s.logger.Error("failed to sync ecs resources", zap.Error(err))
continue
}
s.logger.Info("successfully synced all ecs resources")
}
}
}

func (s *Store) GetECSManifests(appID string) (provider.ECSManifests, bool) {
return s.store.getECSManifests(appID)
}

func (s *Store) GetState(appID string) (State, bool) {
return s.store.getState(appID)
}

func (s *Store) WaitForReady(ctx context.Context, timeout time.Duration) error {
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()

select {
case <-ctx.Done():
return nil
case err := <-s.firstSyncedCh:
return err
}
}
Loading