diff --git a/components/provisioner/internal/operations/stages/provisioning/create_operators_bindings.go b/components/provisioner/internal/operations/stages/provisioning/create_operators_bindings.go index c9cc547b7b..6ff0f15061 100644 --- a/components/provisioner/internal/operations/stages/provisioning/create_operators_bindings.go +++ b/components/provisioner/internal/operations/stages/provisioning/create_operators_bindings.go @@ -17,6 +17,9 @@ import ( "github.com/kyma-project/control-plane/components/provisioner/internal/operations" "github.com/kyma-project/control-plane/components/provisioner/internal/util" "github.com/kyma-project/control-plane/components/provisioner/internal/util/k8s" + + core "k8s.io/api/core/v1" + v1core "k8s.io/client-go/kubernetes/typed/core/v1" ) const ( @@ -96,6 +99,10 @@ func (s *CreateBindingsForOperatorsStep) Run(cluster model.Cluster, _ model.Oper return operations.StageResult{}, err.Append("failed to create k8s client").SetComponent(apperrors.ErrClusterK8SClient) } + if err := s.createNamespace(k8sClient.CoreV1().Namespaces(), "istio-system"); err != nil { + return operations.StageResult{}, err + } + clusterRoles := make([]v12.ClusterRole, 0) clusterRoles = append(clusterRoles, buildClusterRole( @@ -240,3 +247,15 @@ func createClusterRoleBindings(crbClient v1.ClusterRoleBindingInterface, cluster } return nil } + +func (c *CreateBindingsForOperatorsStep) createNamespace(namespaceInterface v1core.NamespaceInterface, namespace string) apperrors.AppError { + ns := &core.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: namespace}, + } + _, err := namespaceInterface.Create(context.Background(), ns, metav1.CreateOptions{}) + + if err != nil && !k8serrors.IsAlreadyExists(err) { + return util.K8SErrorToAppError(errors.Wrap(err, "Failed to create namespace")) + } + return nil +} diff --git a/components/provisioner/internal/operations/stages/provisioning/create_operators_bindings_test.go b/components/provisioner/internal/operations/stages/provisioning/create_operators_bindings_test.go index 10f75b2357..3a4f0c4a83 100644 --- a/components/provisioner/internal/operations/stages/provisioning/create_operators_bindings_test.go +++ b/components/provisioner/internal/operations/stages/provisioning/create_operators_bindings_test.go @@ -19,6 +19,7 @@ import ( "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + core "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/fake" ) @@ -104,6 +105,32 @@ func TestCreateBindingsForOperatorsStep_Run(t *testing.T) { assert.Equal(t, time.Duration(0), result.Delay) }) + t.Run("should not fail if namespace istio-system already exists", func(t *testing.T) { + // given + k8sClient := fake.NewSimpleClientset() + + ns := &core.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "istio-system"}, + } + + _, err := k8sClient.CoreV1().Namespaces().Create(context.Background(), ns, metav1.CreateOptions{}) + + require.NoError(t, err) + + k8sClientProvider := &mocks.K8sClientProvider{} + k8sClientProvider.On("CreateK8SClient", dynamicKubeconfig).Return(k8sClient, nil) + + step := NewCreateBindingsForOperatorsStep(k8sClientProvider, operatorBindingConfig, dynamicKubeconfigProvider, nextStageName, time.Minute) + + // when + result, err := step.Run(cluster, model.Operation{}, &logrus.Entry{}) + + // then + require.NoError(t, err) + assert.Equal(t, nextStageName, result.Stage) + assert.Equal(t, time.Duration(0), result.Delay) + }) + t.Run("should attempt retry when failed to get dynamic kubeconfig", func(t *testing.T) { // given dynamicKubeconfigProvider := &provisioning_mocks.DynamicKubeconfigProvider{}