Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
51 changes: 50 additions & 1 deletion .github/actions/collect-cluster-info/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,54 @@ runs:
steps:
- name: collect cluster-info
if: ${{ always() }}
run: make -C tests/operator cluster-info
run: |
echo "####################"
echo "kubectl get pods -A"
echo "####################"
kubectl get pods -A || true

echo "########################"
echo "kubectl get functions -A"
echo "########################"
kubectl get functions -A || true

echo "################################"
echo "kubectl get serverless -A -oyaml"
echo "################################"
kubectl get serverless -A -oyaml || true

echo "##########################################################"
echo "Describe serverless operator deploy"
echo "kubectl describe deploy -A -l app.kubernetes.io/name=serverless-operator"
echo "##########################################################"
kubectl describe deploy -A -l app.kubernetes.io/name=serverless-operator || true

echo "####################################################################"
echo "Describe serverless controller deploy"
echo "kubectl describe deploy -A -l app.kubernetes.io/name=serverless"
echo "####################################################################"
kubectl describe deploy -A -l app.kubernetes.io/name=serverless || true

echo "##########################################################"
echo "Get serverless operator pod"
echo "kubectl get pod -A -l app.kubernetes.io/name=serverless-operator -oyaml"
echo "##########################################################"
kubectl get pod -A -l app.kubernetes.io/name=serverless-operator -oyaml || true

echo "####################################################################"
echo "Get serverless controller pod"
echo "kubectl get pod -A -l app.kubernetes.io/name=serverless -oyaml"
echo "####################################################################"
kubectl get pod -A -l app.kubernetes.io/name=serverless -oyaml || true

echo "########################################################################################################"
echo "Serverless operator logs"
echo "kubectl logs -n kyma-system -l app.kubernetes.io/name=serverless-operator --tail=-1"
echo "########################################################################################################"
kubectl logs -n kyma-system -l app.kubernetes.io/name=serverless-operator --tail=-1 || true

echo "########################################################"
echo "Serverless controller logs across all namespaces"
echo "########################################################"
for n in `kubectl get namespaces -o json | jq -r ".items[].metadata.name"`; do kubectl logs -l app.kubernetes.io/name=serverless --tail=-1 -n $n; done || true
shell: bash
10 changes: 5 additions & 5 deletions .github/workflows/promote-to-release-channel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
working-directory: module-manifests
run: |
git fetch upstream
git checkout -B "${MODULE_VERSION}" upstream/main
git checkout -B "serverless-${MODULE_VERSION}" upstream/main

mkdir -p modules/serverless/${MODULE_VERSION}
cp ../module-config.yaml modules/serverless/${MODULE_VERSION}/module-config.yaml
Expand All @@ -64,20 +64,20 @@ jobs:

git add .
git commit -m "promote serverless ${MODULE_VERSION}"
git push origin "${MODULE_VERSION}" -f
git push origin "serverless-${MODULE_VERSION}" -f

- name: Create PullRequest to module-manifests
working-directory: module-manifests
run: |
prs=$(gh pr list -R "https://${GH_TOOLS_REPO_URL}/kyma/module-manifests" -A "${BOT_USERNAME}" --state open --json headRefName)

if echo $prs | jq -e ".[] | select(.headRefName==\"${MODULE_VERSION}\")"; then
if echo $prs | jq -e ".[] | select(.headRefName==\"serverless-${MODULE_VERSION}\")"; then
echo "opened PR already exists, no need to create new one, PR will be updated by push from previous step"
exit 0
fi

gh pr create -B main --fill \
-H "${BOT_USERNAME}:${MODULE_VERSION}" \
-H "${BOT_USERNAME}:serverless-${MODULE_VERSION}" \
-R "https://${GH_TOOLS_REPO_URL}/kyma/module-manifests/" \
--title "Promote Serverless ${MODULE_VERSION}" \
--body "https://github.com/kyma-project/serverless/actions/${{github.run_id}}"
--body "Adding Serverless [${MODULE_VERSION}](https://github.com/kyma-project/serverless/releases/tag/${MODULE_VERSION})"
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ func (d *Deployment) initContainerCommand() string {
var arr []string
arr = append(arr, "/app/gitcloner")
arr = append(arr,
fmt.Sprintf("mkdir /git-repository/src;cp /git-repository/repo/%s/* /git-repository/src;",
fmt.Sprintf("mkdir /git-repository/src;cp -r '/git-repository/repo/%s'/* /git-repository/src;",
strings.Trim(gitRepo.BaseDir, "/ ")))
return strings.Join(arr, "\n")
}
Expand Down Expand Up @@ -521,7 +521,7 @@ func runtimeCommandGitSources(f *serverlessv1alpha2.Function) string {
if f.HasNodejsRuntime() {
result = append(result, `echo "{}" > package.json;`)
}
result = append(result, `cp /git-repository/src/* .;`)
result = append(result, `cp -r /git-repository/src/* .;`)
return strings.Join(result, "\n")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,27 @@ fi`,
c := r.Spec.Template.Spec.InitContainers[0]
expectedCommand := []string{"sh", "-c",
`/app/gitcloner
mkdir /git-repository/src;cp /git-repository/repo/recursing-mcnulty/* /git-repository/src;`}
mkdir /git-repository/src;cp -r '/git-repository/repo/recursing-mcnulty'/* /git-repository/src;`}
require.Equal(t, expectedCommand, c.Command)
})
t.Run("create init container for git function with baseDir containing whitespaces", func(t *testing.T) {
d := minimalDeployment()
d.commit = "test-commit"
d.function.Spec.Source = serverlessv1alpha2.Source{
GitRepository: &serverlessv1alpha2.GitRepositorySource{
URL: "wonderful-germain",
Repository: serverlessv1alpha2.Repository{
BaseDir: "git functions/nodejs12",
Reference: "main"}}}

r := d.construct()

require.NotNil(t, r)
require.Len(t, r.Spec.Template.Spec.InitContainers, 1)
c := r.Spec.Template.Spec.InitContainers[0]
expectedCommand := []string{"sh", "-c",
`/app/gitcloner
mkdir /git-repository/src;cp -r '/git-repository/repo/git functions/nodejs12'/* /git-repository/src;`}
require.Equal(t, expectedCommand, c.Command)
})
}
Expand Down Expand Up @@ -1306,7 +1326,7 @@ fi`,
},
},
},
want: `cp /git-repository/src/* .;
want: `cp -r /git-repository/src/* .;
PIP_CONFIG_FILE=package-registry-config/pip.conf pip install --user --no-cache-dir -r requirements.txt;
cd ..;
if [ -f "./kubeless.py" ]; then
Expand Down Expand Up @@ -1371,7 +1391,7 @@ npm start;`,
},
},
want: `echo "{}" > package.json;
cp /git-repository/src/* .;
cp -r /git-repository/src/* .;
npm install --prefer-offline --no-audit --progress=false;
cd ..;
npm start;`,
Expand Down Expand Up @@ -1431,7 +1451,7 @@ npm start;`,
},
},
want: `echo "{}" > package.json;
cp /git-repository/src/* .;
cp -r /git-repository/src/* .;
npm install --prefer-offline --no-audit --progress=false;
cd ..;
npm start;`,
Expand Down
28 changes: 18 additions & 10 deletions components/operator/api/v1alpha1/serverless_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,23 @@ const (
// prerequisites and soft dependencies
ConditionTypeConfigured = ConditionType("Configured")

// serverless controller deployment failure details
ConditionTypeDeploymentFailure = ConditionType("DeploymentFailure")

// deletion
ConditionTypeDeleted = ConditionType("Deleted")

ConditionReasonConfiguration = ConditionReason("Configuration")
ConditionReasonConfigurationErr = ConditionReason("ConfigurationErr")
ConditionReasonConfigured = ConditionReason("Configured")
ConditionReasonInstallation = ConditionReason("Installation")
ConditionReasonInstallationErr = ConditionReason("InstallationErr")
ConditionReasonInstalled = ConditionReason("Installed")
ConditionReasonServerlessDuplicated = ConditionReason("ServerlessDuplicated")
ConditionReasonDeletion = ConditionReason("Deletion")
ConditionReasonDeletionErr = ConditionReason("DeletionErr")
ConditionReasonDeleted = ConditionReason("Deleted")
ConditionReasonConfiguration = ConditionReason("Configuration")
ConditionReasonConfigurationErr = ConditionReason("ConfigurationErr")
ConditionReasonConfigured = ConditionReason("Configured")
ConditionReasonInstallation = ConditionReason("Installation")
ConditionReasonInstallationErr = ConditionReason("InstallationErr")
ConditionReasonInstalled = ConditionReason("Installed")
ConditionReasonDeploymentReplicaFailure = ConditionReason("DeploymentReplicaFailure")
ConditionReasonServerlessDuplicated = ConditionReason("ServerlessDuplicated")
ConditionReasonDeletion = ConditionReason("Deletion")
ConditionReasonDeletionErr = ConditionReason("DeletionErr")
ConditionReasonDeleted = ConditionReason("Deleted")

Finalizer = "serverless-operator.kyma-project.io/deletion-hook"
)
Expand Down Expand Up @@ -199,6 +203,10 @@ func (s *Serverless) UpdateConditionTrue(c ConditionType, r ConditionReason, msg
meta.SetStatusCondition(&s.Status.Conditions, condition)
}

func (s *Serverless) RemoveCondition(c ConditionType) {
_ = meta.RemoveStatusCondition(&s.Status.Conditions, string(c))
}

func (s *Serverless) IsServedEmpty() bool {
return s.Status.Served == ""
}
Expand Down
18 changes: 16 additions & 2 deletions components/operator/controllers/serverless_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/kyma-project/serverless/components/operator/internal/tracing"
"github.com/pkg/errors"
"go.uber.org/zap"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/record"
Expand Down Expand Up @@ -63,9 +64,14 @@ func (sr *serverlessReconciler) SetupWithManager(mgr ctrl.Manager) error {
Watches(&v1alpha1.Serverless{}, &handler.Funcs{
// retrigger all Serverless CRs reconciliations when one is deleted
// this should ensure at least one Serverless CR is served
DeleteFunc: sr.retriggerAllServerlessCRs,
DeleteFunc: sr.retriggerAllServerlessCRsOnDelete,
}).
Watches(&corev1.Service{}, tracing.ServiceCollectorWatcher()).
Watches(&appsv1.Deployment{}, &handler.Funcs{
// retrigger all Serverless CRs reconciliations when a serverless-controller Deployment is updated or deleted
UpdateFunc: sr.retriggerAllServerlessCRsOnUpdate,
DeleteFunc: sr.retriggerAllServerlessCRsOnDelete,
}, builder.WithPredicates(predicate.NewExactLabelPredicate("app.kubernetes.io/managed-by", "serverless-operator"))).
Complete(sr)
}

Expand All @@ -87,7 +93,15 @@ func (sr *serverlessReconciler) Reconcile(ctx context.Context, req ctrl.Request)
return r.Reconcile(ctx, *instance)
}

func (sr *serverlessReconciler) retriggerAllServerlessCRs(ctx context.Context, e event.DeleteEvent, q workqueue.TypedRateLimitingInterface[ctrl.Request]) {
func (sr *serverlessReconciler) retriggerAllServerlessCRsOnUpdate(ctx context.Context, _ event.TypedUpdateEvent[client.Object], q workqueue.TypedRateLimitingInterface[ctrl.Request]) {
sr.retriggerAllServerlessCRs(ctx, q)
}

func (sr *serverlessReconciler) retriggerAllServerlessCRsOnDelete(ctx context.Context, _ event.TypedDeleteEvent[client.Object], q workqueue.TypedRateLimitingInterface[ctrl.Request]) {
sr.retriggerAllServerlessCRs(ctx, q)
}

func (sr *serverlessReconciler) retriggerAllServerlessCRs(ctx context.Context, q workqueue.TypedRateLimitingInterface[ctrl.Request]) {
log := sr.log.With("deletion_watcher")

list := &v1alpha1.ServerlessList{}
Expand Down
10 changes: 3 additions & 7 deletions components/operator/controllers/serverless_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,20 +128,16 @@ func shouldCreateServerless(h testHelper, serverlessName, serverlessDeploymentNa

// we have to update deployment status manually
h.updateDeploymentStatus(serverlessDeploymentName)
h.updateReplicaSetStatus(serverlessDeploymentName)

// assert
Eventually(h.createGetServerlessStatusFunc(serverlessName)).
Eventually(h.createGetServerlessStatusFunc(serverlessName, serverlessDeploymentName)).
WithPolling(time.Second * 2).
WithTimeout(time.Second * 20).
Should(ConditionTrueMatcher())
}

func shouldPropagateSpecProperties(h testHelper, expected serverlessData) {
Eventually(h.createCheckRegistrySecretFunc(serverlessRegistrySecret, expected.registrySecretData)).
WithPolling(time.Second * 2).
WithTimeout(time.Second * 10).
Should(BeTrue())

Eventually(h.createCheckOptionalDependenciesFunc(serverlessDeploymentName, expected)).
WithPolling(time.Second * 2).
WithTimeout(time.Second * 10).
Expand Down Expand Up @@ -169,7 +165,7 @@ func shouldUpdateServerless(h testHelper, serverlessSpec v1alpha1.ServerlessSpec

Expect(serverless.Spec).To(Equal(serverlessSpec))

Eventually(h.createGetServerlessStatusFunc(serverlessName)).
Eventually(h.createGetServerlessStatusFunc(serverlessName, serverlessDeploymentName)).
WithPolling(time.Second * 2).
WithTimeout(time.Second * 20).
Should(ConditionTrueMatcher())
Expand Down
Loading
Loading