Skip to content

Commit

Permalink
Implement QuickSyncPlan for k8s plugin (#5020)
Browse files Browse the repository at this point in the history
* Implement QuickSyncPlan for k8s plugin

Signed-off-by: Shinnosuke Sawada <[email protected]>

* Fix build and add TODO comment

Signed-off-by: Shinnosuke Sawada <[email protected]>

* Use deploysource.NewLocalSourceCloner to clone source code

Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>

* Fix localSourceCloner.Clone to checkout target revision

Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>

* Format sources

Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>

* Remove unused function

Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>

* Add licence

Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>

* Fix kubernetes application spec nil checks

Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>

---------

Signed-off-by: Shinnosuke Sawada <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: khanhtc1202 <[email protected]>
  • Loading branch information
Warashi authored and khanhtc1202 committed Jul 12, 2024
1 parent 0735096 commit 4096b70
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 8 deletions.
10 changes: 8 additions & 2 deletions pkg/app/piped/deploysource/sourcecloner.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ func (d *localSourceCloner) RevisionName() string {
}

func (d *localSourceCloner) Clone(ctx context.Context, dest string) error {
_, err := d.repo.Copy(dest)
return err
repo, err := d.repo.Copy(dest)
if err != nil {
return err
}
if err := repo.Checkout(ctx, d.revision); err != nil {
return err
}
return nil
}
10 changes: 8 additions & 2 deletions pkg/app/pipedv1/deploysource/sourcecloner.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ func (d *localSourceCloner) RevisionName() string {
}

func (d *localSourceCloner) Clone(ctx context.Context, dest string) error {
_, err := d.repo.Copy(dest)
return err
repo, err := d.repo.Copy(dest)
if err != nil {
return err
}
if err := repo.Checkout(ctx, d.revision); err != nil {
return err
}
return nil
}
38 changes: 38 additions & 0 deletions pkg/app/pipedv1/plugin/inputs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// 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 plugin

import (
"os/exec"

"github.com/pipe-cd/pipecd/pkg/app/pipedv1/deploysource"
"github.com/pipe-cd/pipecd/pkg/git"
"github.com/pipe-cd/pipecd/pkg/plugin/api/v1alpha1/platform"
)

func GetPlanSourceCloner(input *platform.PlanPluginInput) (deploysource.SourceCloner, error) {
gitPath, err := exec.LookPath("git")
if err != nil {
return nil, err
}

cloner := deploysource.NewLocalSourceCloner(
git.NewRepo(input.GetSourceRemoteUrl(), gitPath, input.GetSourceRemoteUrl(), input.GetDeployment().GetGitPath().GetRepo().GetBranch(), nil),
"target",
input.GetDeployment().GetGitPath().GetRepo().GetBranch(),
)

return cloner, nil
}
50 changes: 48 additions & 2 deletions pkg/app/pipedv1/plugin/platform/kubernetes/planner/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,27 @@ package planner
import (
"context"
"fmt"
"io"
"os"
"time"

"github.com/pipe-cd/pipecd/pkg/app/pipedv1/deploysource"
"github.com/pipe-cd/pipecd/pkg/app/pipedv1/plugin"
"github.com/pipe-cd/pipecd/pkg/plugin/api/v1alpha1/platform"
"github.com/pipe-cd/pipecd/pkg/regexpool"

"go.uber.org/zap"
"google.golang.org/grpc"
)

type secretDecrypter interface {
Decrypt(string) (string, error)
}

type PlannerService struct {
platform.UnimplementedPlannerServiceServer

Decrypter secretDecrypter
RegexPool *regexpool.Pool
Logger *zap.Logger
}
Expand All @@ -38,8 +48,12 @@ func (a *PlannerService) Register(server *grpc.Server) {
}

// NewPlannerService creates a new planService.
func NewPlannerService(logger *zap.Logger) *PlannerService {
func NewPlannerService(
decrypter secretDecrypter,
logger *zap.Logger,
) *PlannerService {
return &PlannerService{
Decrypter: decrypter,
RegexPool: regexpool.DefaultPool(),
Logger: logger.Named("planner"),
}
Expand All @@ -63,7 +77,39 @@ func (ps *PlannerService) DetermineStrategy(ctx context.Context, in *platform.De
}

func (ps *PlannerService) QuickSyncPlan(ctx context.Context, in *platform.QuickSyncPlanRequest) (*platform.QuickSyncPlanResponse, error) {
return nil, fmt.Errorf("not implemented yet")
now := time.Now()

cloner, err := plugin.GetPlanSourceCloner(in.GetInput())
if err != nil {
return nil, err
}

d, err := os.MkdirTemp("", "") // TODO
if err != nil {
return nil, fmt.Errorf("failed to prepare temporary directory (%w)", err)
}
defer os.RemoveAll(d)

p := deploysource.NewProvider(
d,
cloner,
*in.GetInput().GetDeployment().GetGitPath(),
ps.Decrypter,
)

ds, err := p.GetReadOnly(ctx, io.Discard /* TODO */)
if err != nil {
return nil, err
}

cfg := ds.ApplicationConfig.KubernetesApplicationSpec
if cfg == nil {
return nil, fmt.Errorf("missing KubernetesApplicationSpec in application configuration")
}

return &platform.QuickSyncPlanResponse{
Stages: buildQuickSyncPipeline(*cfg.Input.AutoRollback, now),
}, nil
}

func (ps *PlannerService) PipelineSyncPlan(ctx context.Context, in *platform.PipelineSyncPlanRequest) (*platform.PipelineSyncPlanResponse, error) {
Expand Down
7 changes: 5 additions & 2 deletions pkg/app/pipedv1/plugin/platform/kubernetes/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,11 @@ func (s *server) run(ctx context.Context, input cli.Input) (runErr error) {
// Start a gRPC server for handling external API requests.
{
var (
service = planner.NewPlannerService(input.Logger)
opts = []rpc.Option{
service = planner.NewPlannerService(
nil, // TODO: Inject the real secret decrypter. It should be a instance of pipedv1/plugin/secrets.Decrypter.
input.Logger,
)
opts = []rpc.Option{
rpc.WithPort(s.apiPort),
rpc.WithGracePeriod(s.gracePeriod),
rpc.WithLogger(input.Logger),
Expand Down
34 changes: 34 additions & 0 deletions pkg/app/pipedv1/plugin/secrets/decrypter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// 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 secrets

import (
"context"
"fmt"

"github.com/pipe-cd/pipecd/pkg/app/pipedv1/cmd/piped/service"
)

type Decrypter struct {
client service.PluginServiceClient
}

func (d *Decrypter) Decrypt(src string) (string, error) {
r, err := d.client.DecryptSecret(context.TODO(), &service.DecryptSecretRequest{Secret: src})
if err != nil {
return "", fmt.Errorf("failed to decrypt secret: %w", err)
}
return r.GetDecryptedSecret(), nil
}

0 comments on commit 4096b70

Please sign in to comment.