Skip to content

Commit

Permalink
Merge branch 'master' into mysql-blueprint-kopia-repository-server
Browse files Browse the repository at this point in the history
  • Loading branch information
r4rajat authored Sep 14, 2023
2 parents 14fd311 + d847e11 commit a478c57
Show file tree
Hide file tree
Showing 20 changed files with 240 additions and 117 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/atlas-image-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
with:
fetch-depth: 0
- uses: tj-actions/changed-files@246636f5fa148b5ad8e65ca4c57b18af3123e5f6 # v39
- uses: tj-actions/changed-files@6ee9cdc5816333acda68e01cf12eedc619e28316 # v39
name: Get changed files
id: changed-files
with:
Expand All @@ -36,10 +36,10 @@ jobs:
if: needs.check-files.outputs.changed == 'true'
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
- name: Image metadata
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
Expand All @@ -48,13 +48,13 @@ jobs:
{{date 'YYYY.MM.DD-HHmm'}}
${{ inputs.tag }}
- name: Login to GHCR
uses: docker/login-action@v2
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
with:
context: "{{defaultContext}}:docker/mongodb-atlas"
push: true
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/kanister-image-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ jobs:
# if: needs.check-files.outputs.changed == 'true'
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
- name: Image metadata
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
Expand All @@ -51,13 +51,13 @@ jobs:
{{date 'YYYY.MM.DD-HHmm'}}
${{ inputs.tag }}
- name: Login to GHCR
uses: docker/login-action@v2
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
with:
context: "{{defaultContext}}:docker/build"
push: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ jobs:
- uses: actions/download-artifact@v3
with:
name: src
- uses: docker/login-action@v2
- uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG base_image=registry.access.redhat.com/ubi9/ubi-minimal:9.2-717
ARG base_image=registry.access.redhat.com/ubi9/ubi-minimal:9.2-750
FROM ${base_image}
ARG kanister_version

Expand Down
2 changes: 1 addition & 1 deletion docker/controller/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.2-717
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.2-750

LABEL maintainer="Tom Manville<[email protected]>"

Expand Down
2 changes: 1 addition & 1 deletion docker/mongodb-atlas/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.2-717
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.2-750

RUN cat >/etc/yum.repos.d/mongodb.repo <<EOL
[mongodb-org-6.0]
Expand Down
2 changes: 1 addition & 1 deletion docker/tools/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ RUN apt-get update && apt-get -y install ca-certificates && \
USER kopia:kopia

# Build tools image
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.2-717
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.2-750
ARG kan_tools_version="test-version"
LABEL name="kanister-tools" \
vendor="Kanister" \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package repositoryserver

import (
"context"
"encoding/json"
"fmt"
"os"
"strconv"
Expand All @@ -28,6 +29,7 @@ import (
k8sresource "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/version"
"k8s.io/client-go/discovery"
Expand Down Expand Up @@ -66,6 +68,13 @@ type RepoServerControllerSuite struct {
k8sServerVersion *version.Info
}

// patchStringValue specifies a patch operation for a string.
type patchStringValue struct {
Op string `json:"op"`
Path string `json:"path"`
Value string `json:"value"`
}

var _ = Suite(&RepoServerControllerSuite{})

func (s *RepoServerControllerSuite) SetUpSuite(c *C) {
Expand Down Expand Up @@ -214,25 +223,32 @@ func (s *RepoServerControllerSuite) TestRepositoryServerImmutability(c *C) {
if s.k8sServerVersion.Major == "1" && minorVersion < 25 {
c.Skip("skipping the test since CRD validation rules feature is enabled only after k8s version 1.25")
}
// Create a repository server CR.

ctx := context.Background()

repoServerCR := testutil.GetTestKopiaRepositoryServerCR(s.repoServerControllerNamespace)
setRepositoryServerSecretsInCR(&s.repoServerSecrets, &repoServerCR)

repoServerCRCreated, err := s.crCli.RepositoryServers(s.repoServerControllerNamespace).Create(context.Background(), &repoServerCR, metav1.CreateOptions{})
// Create a repository server CR
repoServerCRCreated, err := s.crCli.RepositoryServers(s.repoServerControllerNamespace).Create(ctx, &repoServerCR, metav1.CreateOptions{})
c.Assert(err, IsNil)

// Update the repository server CR's Immutable field.
repoServerCRCreated.Spec.Repository.RootPath = "/updated-test-path/"
_, err = s.crCli.RepositoryServers(s.repoServerControllerNamespace).Update(context.Background(), repoServerCRCreated, metav1.UpdateOptions{})
// Expect an error.
//Update the repository server CR's Immutable field.
patch := []patchStringValue{{
Op: "replace",
Path: "/spec/repository/rootPath",
Value: "/updated-test-path/",
}}
patchBytes, _ := json.Marshal(patch)
_, err = s.crCli.RepositoryServers(s.repoServerControllerNamespace).Patch(ctx, repoServerCRCreated.Name, types.JSONPatchType, patchBytes, metav1.PatchOptions{})
c.Assert(err, NotNil)

// Check Error Message
expectedErrorMessage := fmt.Sprintf("RepositoryServer.cr.kanister.io \"%s\" is invalid: spec.repository.rootPath: Invalid value: \"string\": Value is immutable", repoServerCRCreated.GetName())
c.Assert(err.Error(), Equals, expectedErrorMessage)

// Delete the repository server CR.
err = s.crCli.RepositoryServers(s.repoServerControllerNamespace).Delete(context.Background(), repoServerCRCreated.Name, metav1.DeleteOptions{})
err = s.crCli.RepositoryServers(s.repoServerControllerNamespace).Delete(ctx, repoServerCRCreated.Name, metav1.DeleteOptions{})
c.Assert(err, IsNil)
}

Expand Down
11 changes: 4 additions & 7 deletions pkg/kube/fake_pod_controller_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ import (

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)

// FakePodControllerProcessor implements podControllerProcessor
// FakePodControllerProcessor implements PodControllerProcessor
type FakePodControllerProcessor struct {
InWaitForPodReadyNamespace string
InWaitForPodReadyPodName string
Expand All @@ -37,25 +36,23 @@ type FakePodControllerProcessor struct {
InDeletePodOptions metav1.DeleteOptions
DeletePodErr error

InCreatePodCli kubernetes.Interface
InCreatePodOptions *PodOptions
CreatePodRet *corev1.Pod
CreatePodErr error
}

func (f *FakePodControllerProcessor) CreatePod(_ context.Context, cli kubernetes.Interface, options *PodOptions) (*corev1.Pod, error) {
f.InCreatePodCli = cli
func (f *FakePodControllerProcessor) CreatePod(_ context.Context, options *PodOptions) (*corev1.Pod, error) {
f.InCreatePodOptions = options
return f.CreatePodRet, f.CreatePodErr
}

func (f *FakePodControllerProcessor) WaitForPodCompletionPCP(ctx context.Context, namespace, podName string) error {
func (f *FakePodControllerProcessor) WaitForPodCompletion(_ context.Context, namespace, podName string) error {
f.InWaitForPodCompletionNamespace = namespace
f.InWaitForPodCompletionPodName = podName
return f.WaitForPodCompletionErr
}

func (f *FakePodControllerProcessor) WaitForPodReadyPCP(ctx context.Context, namespace, podName string) error {
func (f *FakePodControllerProcessor) WaitForPodReady(_ context.Context, namespace, podName string) error {
f.InWaitForPodReadyPodName = podName
f.InWaitForPodReadyNamespace = namespace
return f.WaitForPodReadyErr
Expand Down
20 changes: 8 additions & 12 deletions pkg/kube/pod_command_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import (
"k8s.io/client-go/kubernetes"
)

// ExecError is an error returned by PodCommandExecutor.Exec
// It contains not only error happened during an execution, but also keeps tails of stdout/stderr streams.
// These tails could be used by the invoker to construct more precise error.
type ExecError struct {
error
stdout LogTail
Expand Down Expand Up @@ -48,27 +51,24 @@ func (e *ExecError) Stderr() string {
return e.stderr.ToString()
}

// PodCommandExecutor allows us to execute command within the pod
// PodCommandExecutor provides a way to execute a command within the pod.
// Is intended to be returned by PodController and works with pod controlled by it.
type PodCommandExecutor interface {
Exec(ctx context.Context, command []string, stdin io.Reader, stdout, stderr io.Writer) error
}

// podCommandExecutorProcessor aids in unit testing
type podCommandExecutorProcessor interface {
execWithOptions(cli kubernetes.Interface, opts ExecOptions) (string, string, error)
}

// podCommandExecutor keeps everything required to execute command within a pod
type podCommandExecutor struct {
cli kubernetes.Interface
namespace string
podName string
containerName string

pcep podCommandExecutorProcessor
pcep PodCommandExecutorProcessor
}

// Exec runs the command and logs stdout and stderr.
// In case of execution error, ExecError will be returned
func (p *podCommandExecutor) Exec(ctx context.Context, command []string, stdin io.Reader, stdout, stderr io.Writer) error {
var (
stderrTail = NewLogTail(logTailDefaultLength)
Expand All @@ -95,7 +95,7 @@ func (p *podCommandExecutor) Exec(ctx context.Context, command []string, stdin i
}

go func() {
_, _, err = p.pcep.execWithOptions(p.cli, opts)
_, _, err = p.pcep.ExecWithOptions(opts)
close(cmdDone)
}()

Expand All @@ -114,7 +114,3 @@ func (p *podCommandExecutor) Exec(ctx context.Context, command []string, stdin i

return err
}

func (p *podCommandExecutor) execWithOptions(cli kubernetes.Interface, opts ExecOptions) (string, string, error) {
return ExecWithOptions(p.cli, opts)
}
35 changes: 35 additions & 0 deletions pkg/kube/pod_command_executor_processor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2023 The Kanister 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 kube

import (
"k8s.io/client-go/kubernetes"
)

// PodCommandExecutorProcessor is an interface wrapping kubernetes API invocation
// it is purposed to be replaced by fake implementation in tests
type PodCommandExecutorProcessor interface {
ExecWithOptions(opts ExecOptions) (string, string, error)
}

type podCommandExecutorProcessor struct {
cli kubernetes.Interface
}

// ExecWithOptions executes a command in the specified pod and container,
// returning stdout, stderr and error.
func (p *podCommandExecutorProcessor) ExecWithOptions(opts ExecOptions) (string, string, error) {
return ExecWithOptions(p.cli, opts)
}
14 changes: 5 additions & 9 deletions pkg/kube/pod_command_executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (

"github.com/pkg/errors"
. "gopkg.in/check.v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
)

Expand Down Expand Up @@ -69,22 +68,20 @@ func (s *testBarrier) SyncWithController() { // background method
}

type fakePodCommandExecutorProcessor struct {
inExecWithOptionsCli kubernetes.Interface
inExecWithOptionsOpts *ExecOptions
execWithOptionsStdout string
execWithOptionsStderr string
execWithOptionsRet1 string
execWithOptionsRet2 string
execWithOptionsErr error

// Signal to `execWithOptions` to start "executing" command.
// Signal to `ExecWithOptions` to start "executing" command.
// Command will remain "executing" until `execWithOptionsSyncEnd.Sync()`
execWithOptionsSyncStart testBarrier
execWithOptionsSyncEnd testBarrier
}

func (fprp *fakePodCommandExecutorProcessor) execWithOptions(cli kubernetes.Interface, opts ExecOptions) (string, string, error) {
fprp.inExecWithOptionsCli = cli
func (fprp *fakePodCommandExecutorProcessor) ExecWithOptions(opts ExecOptions) (string, string, error) {
fprp.inExecWithOptionsOpts = &opts
fprp.execWithOptionsSyncStart.SyncWithController()
if opts.Stdout != nil && len(fprp.execWithOptionsStdout) > 0 {
Expand Down Expand Up @@ -150,7 +147,7 @@ func (s *PodCommandExecutorTestSuite) TestPodRunnerExec(c *C) {
}()
prp.execWithOptionsSyncStart.Sync() // Ensure ExecWithOptions is called
wg.Wait()
prp.execWithOptionsSyncEnd.Sync() // Release execWithOptions
prp.execWithOptionsSyncEnd.Sync() // Release ExecWithOptions

c.Assert(err, Not(IsNil))
c.Assert(errors.Is(err, context.Canceled), Equals, true)
Expand All @@ -171,10 +168,9 @@ func (s *PodCommandExecutorTestSuite) TestPodRunnerExec(c *C) {
}()
prp.execWithOptionsSyncStart.Sync() // Ensure ExecWithOptions is called
wg.Wait()
prp.execWithOptionsSyncEnd.Sync() // Release execWithOptions
prp.execWithOptionsSyncEnd.Sync() // Release ExecWithOptions

c.Assert(err, IsNil)
c.Assert(prp.inExecWithOptionsCli, Equals, cli)
c.Assert(prp.inExecWithOptionsOpts.Command, DeepEquals, command)
c.Assert(prp.inExecWithOptionsOpts.Namespace, Equals, podCommandExecutorNS)
c.Assert(prp.inExecWithOptionsOpts.PodName, Equals, podCommandExecutorPodName)
Expand Down Expand Up @@ -214,7 +210,7 @@ func (s *PodCommandExecutorTestSuite) TestPodRunnerExec(c *C) {
}()
prp.execWithOptionsSyncStart.Sync() // Ensure ExecWithOptions is called
wg.Wait()
prp.execWithOptionsSyncEnd.Sync() // Release execWithOptions
prp.execWithOptionsSyncEnd.Sync() // Release ExecWithOptions

c.Assert(err, Not(IsNil))
c.Assert(prp.inExecWithOptionsOpts.Stdout, Not(IsNil))
Expand Down
Loading

0 comments on commit a478c57

Please sign in to comment.