Skip to content

Commit

Permalink
Merge branch 'main' into fix/k8s-watcher-logs
Browse files Browse the repository at this point in the history
  • Loading branch information
ritwikranjan authored Nov 26, 2024
2 parents bf509b4 + 59424a0 commit e2ce1fa
Show file tree
Hide file tree
Showing 35 changed files with 553 additions and 233 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/perf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ permissions:

jobs:
perf_test:
if: ${{ github.event_name == 'merge_group' }}
if: ${{ github.event_name != 'workflow_run' || github.event_name == 'merge_group' }}
name: Retina Performance Test
runs-on: ubuntu-latest

Expand Down Expand Up @@ -49,11 +49,11 @@ jobs:
shell: bash
run: |
set -euo pipefail
if [ -n "${{ github.event.inputs.tag }}" ]; then
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
TAG=${{ github.event.inputs.tag }}
elif [ "${{ github.event_name }}" == "merge_group" ]; then
TAG=$(git describe --tags `git rev-list --tags --max-count=1`)
TAG=$(make version)
else
TAG="default-version"
TAG=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .tag_name)
fi
go test -v ./test/e2e/. -timeout 2h -tags=perf -count=1 -args -image-tag=$TAG -image-registry=${{ vars.ACR_NAME }} -image-namespace=${{ github.repository }}
58 changes: 16 additions & 42 deletions .github/workflows/scale-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ on:
required: true
type: string
cluster_name:
description: "AKS Cluster Name"
description: "AKS Cluster Name (nodes to receive traffic pods should be labeled with scale-test=true)"
required: true
type: string
location:
description: "Azure Location"
image_namespace:
description: "Image Namespace (if not set, default namespace will be used)"
type: string
image_tag:
description: "Image Tag (if not set, default for this commit will be used)"
type: string
default: ${{ vars.AZURE_LOCATION }}
num_deployments:
description: "Number of Traffic Deployments"
default: 1000
Expand All @@ -27,20 +29,8 @@ on:
description: "Number of Network Policies"
default: 1000
type: number
num_unique_labels_per_pod:
description: "Number of Unique Labels per Pod"
default: 2
type: number
num_unique_labels_per_deployment:
description: "Number of Unique Labels per Deployment"
default: 2
type: number
num_shared_labels_per_pod:
description: "Number of Shared Labels per Pod"
default: 3
type: number
delete_labels:
description: "Delete Labels"
cleanup:
description: "Clean up environment after test"
default: true
type: boolean

Expand All @@ -54,10 +44,6 @@ on:
description: "AKS Cluster Name"
required: true
type: string
location:
description: "Azure Location"
type: string
default: ${{ vars.AZURE_LOCATION }}
num_deployments:
description: "Number of Traffic Deployments"
default: 1000
Expand All @@ -70,20 +56,8 @@ on:
description: "Number of Network Policies"
default: 1000
type: number
num_unique_labels_per_pod:
description: "Number of Unique Labels per Pod"
default: 2
type: number
num_unique_labels_per_deployment:
description: "Number of Unique Labels per Deployment"
default: 2
type: number
num_shared_labels_per_pod:
description: "Number of Shared Labels per Pod"
default: 3
type: number
delete_labels:
description: "Delete Labels"
cleanup:
description: "Clean up environment after test"
default: true
type: boolean

Expand Down Expand Up @@ -116,17 +90,17 @@ jobs:
- name: Run Scale Test
env:
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION }}
AZURE_LOCATION: ${{ input.location }}
AZURE_RESOURCE_GROUP: ${{ inputs.resource_group }}
CLUSTER_NAME: ${{ inputs.cluster_name }}
NUM_DEPLOYMENTS: ${{ inputs.num_deployments }}
NUM_REPLICAS: ${{ inputs.num_replicas }}
NUM_NETPOLS: ${{ inputs.num_netpol }}
NUM_UNIQUE_LABELS_PER_POD: ${{ inputs.num_unique_labels_per_pod }}
NUM_SHARED_LABELS_PER_POD: ${{ inputs.num_shared_labels_per_pod }}
NUM_UNIQUE_LABELS_PER_DEPLOYMENT: ${{ inputs.num_unique_labels_per_deployment }}
DELETE_LABELS: ${{ inputs.delete_labels }}
CLEANUP: ${{ inputs.cleanup }}
IMAGE_REGISTRY: ${{ inputs.image_namespace == '' && vars.ACR_NAME || inputs.image_namespace }}
IMAGE_NAMESPACE: ${{ github.repository }}
TAG: ${{ inputs.image_tag }}
AZURE_APP_INSIGHTS_KEY: ${{ secrets.AZURE_APP_INSIGHTS_KEY }}
shell: bash
run: |
set -euo pipefail
go test -v ./test/e2e/. -timeout 300m -tags=scale -count=1 -args -image-tag=$(make version) -image-registry=${{vars.ACR_NAME}} -image-namespace=${{github.repository}}
go test -v ./test/e2e/. -timeout 300m -tags=scale -count=1 -args -image-tag=$( [[ $TAG == "" ]] && make version || echo $TAG ) -create-infra=false -delete-infra=false
4 changes: 2 additions & 2 deletions .github/workflows/trivy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
strategy:
fail-fast: false
matrix:
image: ["retina-agent", "retina-init", "retina-operator"]
image: ["retina-agent", "retina-init", "retina-operator", "kubectl-retina", "retina-shell"]
runs-on: ubuntu-latest # trivy only supports running on Linux
steps:
- name: Checkout code
Expand All @@ -30,7 +30,7 @@ jobs:
echo "TAG=$(make version)" >> $GITHUB_ENV
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@915b19bbe73b92a6cf82a1bc12b087c9a19a5fe2
uses: aquasecurity/trivy-action@18f2510ee396bbf400402947b394f2dd8c87dbb0
with:
image-ref: "ghcr.io/${{ github.repository }}/${{ matrix.image }}:${{ env.TAG }}"
format: "template"
Expand Down
4 changes: 2 additions & 2 deletions cli/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \
-X "github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID"="$APP_INSIGHTS_ID"" \
-a -o kubectl-retina cli/main.go

# mcr.microsoft.com/cbl-mariner/base/core:2.0
FROM --platform=$TARGETPLATFORM mcr.microsoft.com/cbl-mariner/base/core@sha256:77651116f2e83cf50fddd8a0316945499f8ce6521ff8e94e67539180d1e5975a
# mcr.microsoft.com/cbl-mariner/distroless/minimal:2.0
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/cbl-mariner/distroless/minimal@sha256:db87903c5d4d9d6760e86a274914efd6a3bb5914c0b5a6c6b35350ec297fea4f
WORKDIR /
COPY --from=builder /workspace/kubectl-retina .

11 changes: 7 additions & 4 deletions cli/cmd/capture/capture.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions"
)

var name string
var opts = struct {
genericclioptions.ConfigFlags
Name *string
}{}

const defaultName = "retina-capture"

Expand All @@ -20,7 +23,7 @@ var capture = &cobra.Command{

func init() {
cmd.Retina.AddCommand(capture)
configFlags = genericclioptions.NewConfigFlags(true)
configFlags.AddFlags(capture.PersistentFlags())
capture.PersistentFlags().StringVar(&name, "name", defaultName, "The name of the Retina Capture")
opts.ConfigFlags = *genericclioptions.NewConfigFlags(true)
opts.AddFlags(capture.PersistentFlags())
capture.PersistentFlags().StringVar(opts.Name, "name", defaultName, "The name of the Retina Capture")
}
37 changes: 17 additions & 20 deletions cli/cmd/capture/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/kubernetes"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
Expand All @@ -32,8 +31,6 @@ import (
)

var (
configFlags *genericclioptions.ConfigFlags

blobUpload string
debug bool
duration time.Duration
Expand Down Expand Up @@ -111,7 +108,7 @@ var createCapture = &cobra.Command{
Short: "Create a Retina Capture",
Example: createExample,
RunE: func(*cobra.Command, []string) error {
kubeConfig, err := configFlags.ToRESTConfig()
kubeConfig, err := opts.ToRESTConfig()
if err != nil {
return errors.Wrap(err, "failed to compose k8s rest config")
}
Expand All @@ -134,10 +131,10 @@ var createCapture = &cobra.Command{
if nowait {
retinacmd.Logger.Info("Please manually delete all capture jobs")
if capture.Spec.OutputConfiguration.BlobUpload != nil {
retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", namespace), zap.String("secret name", *capture.Spec.OutputConfiguration.BlobUpload))
retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", *opts.Namespace), zap.String("secret name", *capture.Spec.OutputConfiguration.BlobUpload))
}
if capture.Spec.OutputConfiguration.S3Upload != nil && capture.Spec.OutputConfiguration.S3Upload.SecretName != "" {
retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", namespace), zap.String("secret name", capture.Spec.OutputConfiguration.S3Upload.SecretName))
retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", *opts.Namespace), zap.String("secret name", capture.Spec.OutputConfiguration.S3Upload.SecretName))
}
printCaptureResult(jobsCreated)
return nil
Expand All @@ -154,19 +151,19 @@ var createCapture = &cobra.Command{
retinacmd.Logger.Info("Deleting jobs as all jobs are completed")
jobsFailedToDelete := deleteJobs(kubeClient, jobsCreated)
if len(jobsFailedToDelete) != 0 {
retinacmd.Logger.Info("Please manually delete capture jobs failed to delete", zap.String("namespace", namespace), zap.String("job list", strings.Join(jobsFailedToDelete, ",")))
retinacmd.Logger.Info("Please manually delete capture jobs failed to delete", zap.String("namespace", *opts.Namespace), zap.String("job list", strings.Join(jobsFailedToDelete, ",")))
}

err = deleteSecret(kubeClient, capture.Spec.OutputConfiguration.BlobUpload)
if err != nil {
retinacmd.Logger.Error("Failed to delete capture secret, please manually delete it",
zap.String("namespace", namespace), zap.String("secret name", *capture.Spec.OutputConfiguration.BlobUpload), zap.Error(err))
zap.String("namespace", *opts.Namespace), zap.String("secret name", *capture.Spec.OutputConfiguration.BlobUpload), zap.Error(err))
}

err = deleteSecret(kubeClient, &capture.Spec.OutputConfiguration.S3Upload.SecretName)
if err != nil {
retinacmd.Logger.Error("Failed to delete capture secret, please manually delete it",
zap.String("namespace", namespace),
zap.String("namespace", *opts.Namespace),
zap.String("secret name", capture.Spec.OutputConfiguration.S3Upload.SecretName),
zap.Error(err),
)
Expand All @@ -180,7 +177,7 @@ var createCapture = &cobra.Command{

retinacmd.Logger.Info("Not all job are completed in the given time")
retinacmd.Logger.Info("Please manually delete the Capture")
return getCaptureAndPrintCaptureResult(kubeClient, capture.Name, namespace)
return getCaptureAndPrintCaptureResult(kubeClient, capture.Name, *opts.Namespace)
},
}

Expand All @@ -199,7 +196,7 @@ func createSecretFromBlobUpload(kubeClient kubernetes.Interface, blobUpload, cap
captureConstants.CaptureOutputLocationBlobUploadSecretKey: []byte(blobUpload),
},
}
secret, err := kubeClient.CoreV1().Secrets(namespace).Create(context.TODO(), secret, metav1.CreateOptions{})
secret, err := kubeClient.CoreV1().Secrets(*opts.Namespace).Create(context.TODO(), secret, metav1.CreateOptions{})
if err != nil {
return "", err
}
Expand All @@ -218,7 +215,7 @@ func createSecretFromS3Upload(kubeClient kubernetes.Interface, s3AccessKeyID, s3
captureConstants.CaptureOutputLocationS3UploadSecretAccessKey: []byte(s3SecretAccessKey),
},
}
secret, err := kubeClient.CoreV1().Secrets(namespace).Create(context.TODO(), secret, metav1.CreateOptions{})
secret, err := kubeClient.CoreV1().Secrets(*opts.Namespace).Create(context.TODO(), secret, metav1.CreateOptions{})
if err != nil {
return "", fmt.Errorf("failed to create s3 upload secret: %w", err)
}
Expand All @@ -230,14 +227,14 @@ func deleteSecret(kubeClient kubernetes.Interface, secretName *string) error {
return nil
}

return kubeClient.CoreV1().Secrets(namespace).Delete(context.TODO(), *secretName, metav1.DeleteOptions{})
return kubeClient.CoreV1().Secrets(*opts.Namespace).Delete(context.TODO(), *secretName, metav1.DeleteOptions{}) //nolint:wrapcheck //internal return
}

func createCaptureF(kubeClient kubernetes.Interface) (*retinav1alpha1.Capture, error) {
capture := &retinav1alpha1.Capture{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Name: *opts.Name,
Namespace: *opts.Namespace,
},
Spec: retinav1alpha1.CaptureSpec{
CaptureConfiguration: retinav1alpha1.CaptureConfiguration{
Expand Down Expand Up @@ -322,15 +319,15 @@ func createCaptureF(kubeClient kubernetes.Interface) (*retinav1alpha1.Capture, e

if len(blobUpload) != 0 {
// Mount blob url as secret onto the capture pod for security concern if blob url is not empty.
secretName, err := createSecretFromBlobUpload(kubeClient, blobUpload, name)
secretName, err := createSecretFromBlobUpload(kubeClient, blobUpload, *opts.Name)
if err != nil {
return nil, err
}
capture.Spec.OutputConfiguration.BlobUpload = &secretName
}

if s3Bucket != "" {
secretName, err := createSecretFromS3Upload(kubeClient, s3AccessKeyID, s3SecretAccessKey, name)
secretName, err := createSecretFromS3Upload(kubeClient, s3AccessKeyID, s3SecretAccessKey, *opts.Name)
if err != nil {
return nil, fmt.Errorf("failed to create s3 upload secret: %w", err)
}
Expand Down Expand Up @@ -379,12 +376,12 @@ func createJobs(kubeClient kubernetes.Interface, capture *retinav1alpha1.Capture

jobsCreated := []batchv1.Job{}
for _, job := range jobs {
jobCreated, err := kubeClient.BatchV1().Jobs(namespace).Create(context.TODO(), job, metav1.CreateOptions{})
jobCreated, err := kubeClient.BatchV1().Jobs(*opts.Namespace).Create(context.TODO(), job, metav1.CreateOptions{})
if err != nil {
return nil, err
}
jobsCreated = append(jobsCreated, *jobCreated)
retinacmd.Logger.Info("Packet capture job is created", zap.String("namespace", namespace), zap.String("capture job", jobCreated.Name))
retinacmd.Logger.Info("Packet capture job is created", zap.String("namespace", *opts.Namespace), zap.String("capture job", jobCreated.Name))
}
return jobsCreated, nil
}
Expand Down Expand Up @@ -428,7 +425,7 @@ func waitUntilJobsComplete(kubeClient kubernetes.Interface, jobs []batchv1.Job)

if len(jobsIncompleted) != 0 {
retinacmd.Logger.Info("Not all jobs are completed",
zap.String("namespace", namespace),
zap.String("namespace", *opts.Namespace),
zap.String("Completed jobs", strings.Join(jobsCompleted, ",")),
zap.String("Uncompleted packet capture jobs", strings.Join(jobsIncompleted, ",")),
)
Expand Down
12 changes: 6 additions & 6 deletions cli/cmd/capture/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ var deleteCapture = &cobra.Command{
Short: "Delete a Retina capture",
Example: deleteExample,
RunE: func(*cobra.Command, []string) error {
kubeConfig, err := configFlags.ToRESTConfig()
kubeConfig, err := opts.ToRESTConfig()
if err != nil {
return errors.Wrap(err, "")
}
Expand All @@ -42,7 +42,7 @@ var deleteCapture = &cobra.Command{

captureJobSelector := &metav1.LabelSelector{
MatchLabels: map[string]string{
label.CaptureNameLabel: name,
label.CaptureNameLabel: *opts.Name,
label.AppLabel: captureConstants.CaptureAppname,
},
}
Expand All @@ -51,12 +51,12 @@ var deleteCapture = &cobra.Command{
LabelSelector: labelSelector.String(),
}

jobList, err := kubeClient.BatchV1().Jobs(namespace).List(context.TODO(), jobListOpt)
jobList, err := kubeClient.BatchV1().Jobs(*opts.Namespace).List(context.TODO(), jobListOpt)
if err != nil {
return errors.Wrap(err, "failed to list capture jobs")
}
if len(jobList.Items) == 0 {
return errors.Errorf("capture %s in namespace %s was not found", name, namespace)
return errors.Errorf("capture %s in namespace %s was not found", *opts.Name, *opts.Namespace)
}

for _, job := range jobList.Items {
Expand All @@ -70,13 +70,13 @@ var deleteCapture = &cobra.Command{

for _, volume := range jobList.Items[0].Spec.Template.Spec.Volumes {
if volume.Secret != nil {
if err := kubeClient.CoreV1().Secrets(namespace).Delete(context.TODO(), volume.Secret.SecretName, metav1.DeleteOptions{}); err != nil {
if err := kubeClient.CoreV1().Secrets(*opts.Namespace).Delete(context.TODO(), volume.Secret.SecretName, metav1.DeleteOptions{}); err != nil {
return errors.Wrap(err, "failed to delete capture secret")
}
break
}
}
retinacmd.Logger.Info(fmt.Sprintf("Retina Capture %q delete", name))
retinacmd.Logger.Info(fmt.Sprintf("Retina Capture %q delete", *opts.Name))

return nil
},
Expand Down
4 changes: 2 additions & 2 deletions cli/cmd/capture/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ var downloadCapture = &cobra.Command{
splitPath := strings.SplitN(containerPath, "/", 2) //nolint:gomnd // TODO string splitting probably isn't the right way to parse this URL?
containerName := splitPath[0]

params := storage.ListBlobsParameters{Prefix: name}
params := storage.ListBlobsParameters{Prefix: *opts.Name}
blobList, err := blobService.GetContainerReference(containerName).ListBlobs(params)
if err != nil {
return errors.Wrap(err, "failed to list blobstore ")
}

if len(blobList.Blobs) == 0 {
return errors.Errorf("no blobs found with prefix: %s", name)
return errors.Errorf("no blobs found with prefix: %s", *opts.Name)
}

for _, v := range blobList.Blobs {
Expand Down
Loading

0 comments on commit e2ce1fa

Please sign in to comment.