Implement ManagedServiceAccount resources reconciliation and tests#55
Implement ManagedServiceAccount resources reconciliation and tests#55yxun wants to merge 29 commits into
Conversation
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: yxun The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
mkolesnik
left a comment
There was a problem hiding this comment.
I see this only handles creating MSA but not updating or deleting it.
Is this planned to be handled later, or will you be updating this PR?
| "sigs.k8s.io/controller-runtime/pkg/reconcile" | ||
|
|
||
| meshv1alpha1 "github.com/stolostron/multicluster-mesh-addon/pkg/apis/mesh/v1alpha1" | ||
| msav1alpha1 "open-cluster-management.io/managed-serviceaccount/apis/authentication/v1alpha1" |
There was a problem hiding this comment.
We should use v1beta1.
I know you were worried about the rotation.enabled field being deprecated, but the rotation.validity is still exposed AFAIK so there's no reason to use the older API.
There was a problem hiding this comment.
I have updated this with the v1beta1 version.
| // CreateManagedServiceAccount creates a ManagedServiceAccount resource for a cluster in the ClusterSet | ||
| func (r *Reconciler) CreateManagedServiceAccount(ctx context.Context, cluster clusterv1.ManagedCluster, mesh *meshv1alpha1.MultiClusterMesh) error { | ||
| klog.Infof("Creating a ManagedServiceAccount for a managed cluster: %s", cluster.Name) | ||
| validity, err := time.ParseDuration(mesh.Spec.Security.Discovery.TokenValidity) // this is derived from the MultiClusterMesh spec.security.discovery.tokenValidity |
There was a problem hiding this comment.
Hmm right now in our API the TokenValidity field is defined as a sting that
// Supports hours (h), days (d), weeks (w), or months (m)
This parsing won't work well, but I wonder if we should just change the type of TokenValidity to be metav1.Duration?
There was a problem hiding this comment.
I think so. Changing that TokenValidity type to be metav1.Duration will help aligning it with the following struct field.
https://pkg.go.dev/open-cluster-management.io/managed-serviceaccount@v0.10.0/apis/authentication/v1beta1#ManagedServiceAccountRotation
I will update this in the mesh/v1alpha1 types.
| msa := &msav1alpha1.ManagedServiceAccount{ | ||
| ObjectMeta: metav1.ObjectMeta{ | ||
| Name: fmt.Sprintf("%s-%s", cluster.Name, mesh.Name), // Naming convention: <cluster-name>-<mesh-name> | ||
| Namespace: cluster.Name, |
There was a problem hiding this comment.
You should add labels to the resource so it can be properly deleted.
If you're adding deletion later, then I'm fine with not adding them right now.
| }, | ||
| Spec: msav1alpha1.ManagedServiceAccountSpec{ | ||
| Rotation: msav1alpha1.ManagedServiceAccountRotation{ | ||
| Enabled: false, |
There was a problem hiding this comment.
// Enabled prescribes whether the ServiceAccount token will be rotated before it expires.
// Deprecated: All ServiceAccount tokens will be rotated before they expire regardless of this field.
I thought we don't want to rotate that ServiceAccount token. Anyway, I can set that to true or not set it. The default value is true.
|
|
||
| // Create ManagedServiceAccount resources for each managed cluster | ||
| for _, cluster := range clusters { | ||
| if err := r.CreateManagedServiceAccount(ctx, cluster, mesh); err != nil { |
There was a problem hiding this comment.
What if it already exists?
I reckon this'll fail?
There was a problem hiding this comment.
Yes, the CreateManagedServiceAccount call would fail if the resource already exists. I have updated this part by checking an existing resource first.
| @@ -0,0 +1,314 @@ | |||
| --- | |||
There was a problem hiding this comment.
This filed shouldn't be checked in
There was a problem hiding this comment.
I have updated the Makefile target and removed this additional crd yaml file in this PR.
| CRDDirectoryPaths: []string{ | ||
| filepath.Join("..", "..", "config", "crd"), // Custom MultiClusterMesh CRD | ||
| filepath.Join("..", "..", "test", "integration", "crds", "ocm"), // OCM CRDs | ||
| filepath.Join("..", "..", "test", "integration", "external-crds", "ocm"), // OCM ManagedServiceAccount CRD |
There was a problem hiding this comment.
I reckon we can just keep them in the same directory as other OCM test crds, or at most in a subdirectory there
There was a problem hiding this comment.
right, the Makefile update-test-crds target is pulling that crd yaml in the same ocm test crds directory now.
| Version: "v1alpha1", | ||
| }) | ||
|
|
||
| Expect(k8sClient.List(context.Background(), list, client.InNamespace(cluster1))).To(Succeed()) |
There was a problem hiding this comment.
You should add test that validity gets passed if set by user
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
I have updated the part of the controller code. If the cluster has an existing ManagedServiceAccount resource with the naming convention , it will skip creating or updating it. I can add a TODO and will implement updating existing resources in a follow up PR. |
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
| // Supports hours (h), days (d), weeks (w), or months (m) | ||
| // It is a wrapper around time.Duration which supports correct marshaling to YAML and JSON | ||
| // +optional | ||
| // +kubebuilder:default="1m" |
There was a problem hiding this comment.
Shouldn't default be updated?
(1m == 1 month, but feel free to use a different default if you think its more sane)
| "sigs.k8s.io/controller-runtime/pkg/reconcile" | ||
|
|
||
| meshv1alpha1 "github.com/stolostron/multicluster-mesh-addon/pkg/apis/mesh/v1alpha1" | ||
| msav1v1beta1 "open-cluster-management.io/managed-serviceaccount/apis/authentication/v1beta1" |
There was a problem hiding this comment.
| msav1v1beta1 "open-cluster-management.io/managed-serviceaccount/apis/authentication/v1beta1" | |
| msav1beta1 "open-cluster-management.io/managed-serviceaccount/apis/authentication/v1beta1" |
Did you mean this?
| } | ||
|
|
||
| // Create ManagedServiceAccount resources for each managed cluster | ||
| msaList := &unstructured.UnstructuredList{} |
There was a problem hiding this comment.
Why use unstructured?
You should register the scheme (in main.go) and use the typed structure directly
| }) | ||
|
|
||
| for _, cluster := range clusters { | ||
| if err := r.List(ctx, msaList, client.InNamespace(cluster.Name), |
There was a problem hiding this comment.
Why not simply use client.Get?
e.g.
existing := &msav1beta1.ManagedServiceAccount{}
if err := r.Get(ctx, types.NamespacedName{Name: msaName, Namespace: cluster.Name}, existing) ...
| } | ||
|
|
||
| // CreateManagedServiceAccount creates a ManagedServiceAccount resource for a cluster in the ClusterSet | ||
| func (r *Reconciler) CreateManagedServiceAccount(ctx context.Context, cluster clusterv1.ManagedCluster, mesh *meshv1alpha1.MultiClusterMesh) error { |
There was a problem hiding this comment.
| func (r *Reconciler) CreateManagedServiceAccount(ctx context.Context, cluster clusterv1.ManagedCluster, mesh *meshv1alpha1.MultiClusterMesh) error { | |
| func (r *Reconciler) createManagedServiceAccount(ctx context.Context, cluster clusterv1.ManagedCluster, mesh *meshv1alpha1.MultiClusterMesh) error { |
No reason to make it public
| util.CreateMultiClusterMesh(ctx, k8sClient, meshName, testNs, testClusterSet, meshv1alpha1.OperatorConfig{}) | ||
| awaitReconcileFinished() | ||
|
|
||
| list := &unstructured.UnstructuredList{} |
There was a problem hiding this comment.
Here also, no need to use unstructured, especially since you registered the type in the test schema
|
|
||
| specData := map[string]interface{}{ | ||
| "rotation": map[string]interface{}{ | ||
| "validity": "24h0m", |
There was a problem hiding this comment.
You set it but didn't check it.
Also I think setting custom fields is better checked in a separate test (It)
|
|
||
| msa := &msav1v1beta1.ManagedServiceAccount{ | ||
| ObjectMeta: metav1.ObjectMeta{ | ||
| Name: fmt.Sprintf("%s-%s", cluster.Name, mesh.Name), // Naming convention: <cluster-name>-<mesh-name> |
There was a problem hiding this comment.
I think a better convention would be something like <mesh-namespace>-<mesh-name>-istio-reader
Either way cluster name is stuttering since the ns is already the cluster name in this case.
We can further discuss naming convention on #72 as well.
| Expect(k8sClient.List(context.Background(), list, client.InNamespace(cluster2))).To(Succeed()) | ||
| }) | ||
|
|
||
| When("the ManagedServiceAccount resource exists", func() { |
There was a problem hiding this comment.
I don't think this makes sense as an integration test.
We don't expect MSA resource to be created by the user externally, which is what this test implies.
We expect them to exist in concurrent reconciliation of the same mesh, in which case the correct tests should test that mesh is updated.
| Expect(k8sClient.List(context.Background(), list, client.InNamespace(cluster1))).To(Succeed()) | ||
| Expect(k8sClient.List(context.Background(), list, client.InNamespace(cluster2))).To(Succeed()) |
There was a problem hiding this comment.
These don't really test that the MSA were created as expected.
For all we know, they might've been created by something else, or by the controller but not as we expected them
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
Signed-off-by: Yuanlin Xu <yuanlin.xu@redhat.com>
|
/hold |
|
This PR has been broken into the following four small PRs. All following comments will be addressed in the small PRs.
https://github.com/stolostron/multicluster-mesh-addon/pull/ ? (pending for resolving pr 130 first) |
|
PR needs rebase. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
This PR adds implementations of ManagedServiceAccount reconciliation and tests in the controller.
It implements creation and cleanup of the ManagedServiceAccount related resources for each managed cluster in the ClusterSet.
It builds istio remote Secret resources and creates ManifestWork resources for distributing those Secrets so that istiod control plane can discover remote endpoints from remote cluster API server(s)
References: