Skip to content

Commit 0a8a4ad

Browse files
committed
Add wait with time-out for accept
Signed-off-by: Dominique Vernier <[email protected]>
1 parent 48d853d commit 0a8a4ad

File tree

3 files changed

+137
-81
lines changed

3 files changed

+137
-81
lines changed

pkg/cmd/accept/cmd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,6 @@ func NewCmd(clusteradmFlags *genericclioptionsclusteradm.ClusteradmFlags, stream
4444
}
4545

4646
cmd.Flags().StringVar(&o.clusters, "clusters", "", "Names of the cluster to accept (comma separated)")
47-
47+
cmd.Flags().IntVar(&o.wait, "wait", 0, "the number of second to wait for the managedcluster and CSR")
4848
return cmd
4949
}

pkg/cmd/accept/exec.go

Lines changed: 133 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ import (
55
"context"
66
"fmt"
77
"strings"
8+
"time"
89

910
corev1 "k8s.io/api/core/v1"
11+
"k8s.io/apimachinery/pkg/api/errors"
1012
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13+
"k8s.io/apimachinery/pkg/util/sets"
14+
"k8s.io/apimachinery/pkg/util/wait"
1115
"k8s.io/client-go/kubernetes"
1216
"open-cluster-management.io/clusteradm/pkg/helpers"
1317

@@ -61,95 +65,145 @@ func (o *Options) run() error {
6165
return o.runWithClient(kubeClient, clusterClient)
6266
}
6367

64-
func (o *Options) runWithClient(kubeClient *kubernetes.Clientset, clusterClient *clusterclientset.Clientset) error {
68+
func (o *Options) runWithClient(kubeClient *kubernetes.Clientset, clusterClient *clusterclientset.Clientset) (err error) {
6569
for _, clusterName := range o.values.clusters {
66-
67-
csrs, err := kubeClient.CertificatesV1().CertificateSigningRequests().List(context.TODO(),
68-
metav1.ListOptions{
69-
LabelSelector: fmt.Sprintf("%v = %v", clusterLabel, clusterName),
70+
if o.wait == 0 {
71+
_, err = o.accept(kubeClient, clusterClient, clusterName)
72+
} else {
73+
err = wait.PollImmediate(1*time.Second, time.Duration(o.wait)*time.Second, func() (bool, error) {
74+
return o.accept(kubeClient, clusterClient, clusterName)
7075
})
76+
}
7177
if err != nil {
7278
return err
7379
}
74-
var csr *certificatesv1.CertificateSigningRequest
75-
for _, item := range csrs.Items {
76-
//Does not have the correct name prefix
77-
if !strings.HasPrefix(item.Spec.Username, userNameSignaturePrefix) {
78-
continue
79-
}
80-
//Check groups
81-
var group string
82-
for _, g := range item.Spec.Groups {
83-
if g == groupName {
84-
group = g
85-
break
86-
}
87-
}
88-
//Does not contain the correct group
89-
if len(group) == 0 {
90-
continue
91-
}
92-
//Check if already approved or denied
93-
done := false
94-
for _, c := range item.Status.Conditions {
95-
if c.Type == certificatesv1.CertificateApproved || c.Type == certificatesv1.CertificateDenied {
96-
done = true
97-
break
98-
}
99-
}
100-
if done {
101-
continue
102-
}
103-
csr = &item
104-
break
105-
}
80+
}
81+
return nil
82+
}
10683

107-
if csr != nil {
108-
if !o.ClusteradmFlags.DryRun {
109-
if csr.Status.Conditions == nil {
110-
csr.Status.Conditions = make([]certificatesv1.CertificateSigningRequestCondition, 0)
111-
}
112-
113-
csr.Status.Conditions = append(csr.Status.Conditions, certificatesv1.CertificateSigningRequestCondition{
114-
Status: corev1.ConditionTrue,
115-
Type: certificatesv1.CertificateApproved,
116-
Reason: fmt.Sprintf("%sApprove", helpers.GetExampleHeader()),
117-
Message: fmt.Sprintf("This CSR was approved by %s certificate approve.", helpers.GetExampleHeader()),
118-
LastUpdateTime: metav1.Now(),
119-
})
120-
121-
kubeClient, err := o.ClusteradmFlags.KubectlFactory.KubernetesClientSet()
122-
if err != nil {
123-
return err
124-
}
125-
signingRequest := kubeClient.CertificatesV1().CertificateSigningRequests()
126-
if _, err := signingRequest.UpdateApproval(context.TODO(), csr.Name, csr, metav1.UpdateOptions{}); err != nil {
127-
return err
128-
}
129-
}
130-
fmt.Printf("CSR %s approved\n", csr.Name)
131-
} else {
132-
fmt.Printf("no CSR to approve for cluster %s\n", clusterName)
84+
func (o *Options) accept(kubeClient *kubernetes.Clientset, clusterClient *clusterclientset.Clientset, clusterName string) (bool, error) {
85+
csrApproved, err := o.approveCSR(kubeClient, clusterName)
86+
if err != nil {
87+
return false, err
88+
}
89+
mcUpdated, err := o.updateManagedCluster(clusterClient, clusterName)
90+
if err != nil {
91+
return false, err
92+
}
93+
if csrApproved && mcUpdated {
94+
return true, nil
95+
}
96+
return false, nil
97+
}
98+
99+
func (o *Options) approveCSR(kubeClient *kubernetes.Clientset, clusterName string) (bool, error) {
100+
csrs, err := kubeClient.CertificatesV1().CertificateSigningRequests().List(context.TODO(),
101+
metav1.ListOptions{
102+
LabelSelector: fmt.Sprintf("%v = %v", clusterLabel, clusterName),
103+
})
104+
if err != nil {
105+
if errors.IsNotFound(err) {
106+
return false, nil
107+
}
108+
return false, err
109+
}
110+
var csr *certificatesv1.CertificateSigningRequest
111+
for _, item := range csrs.Items {
112+
//Does not have the correct name prefix
113+
if !strings.HasPrefix(item.Spec.Username, userNameSignaturePrefix) {
114+
continue
115+
}
116+
//Check groups
117+
groups := sets.NewString(item.Spec.Groups...)
118+
if !groups.Has(groupName) {
119+
continue
120+
}
121+
//Check if already approved or denied
122+
approved, denied := GetCertApprovalCondition(&item.Status)
123+
//if alreaady denied, then nothing to do
124+
if denied {
125+
fmt.Printf("CSR %s already denied\n", item.Name)
126+
return true, nil
133127
}
128+
//if alreaady approved, then nothing to do
129+
if approved {
130+
fmt.Printf("CSR %s already approved\n", item.Name)
131+
return true, nil
132+
}
133+
csr = &item
134+
break
135+
}
136+
137+
//no csr found
138+
if csr == nil {
139+
fmt.Printf("no CSR to approve for cluster %s\n", clusterName)
140+
return false, nil
141+
}
142+
//if dry-run don't approve
143+
if o.ClusteradmFlags.DryRun {
144+
return true, nil
145+
}
146+
if csr.Status.Conditions == nil {
147+
csr.Status.Conditions = make([]certificatesv1.CertificateSigningRequestCondition, 0)
148+
}
149+
150+
csr.Status.Conditions = append(csr.Status.Conditions, certificatesv1.CertificateSigningRequestCondition{
151+
Status: corev1.ConditionTrue,
152+
Type: certificatesv1.CertificateApproved,
153+
Reason: fmt.Sprintf("%sApprove", helpers.GetExampleHeader()),
154+
Message: fmt.Sprintf("This CSR was approved by %s certificate approve.", helpers.GetExampleHeader()),
155+
LastUpdateTime: metav1.Now(),
156+
})
157+
158+
kubeClient, err = o.ClusteradmFlags.KubectlFactory.KubernetesClientSet()
159+
if err != nil {
160+
return false, err
161+
}
162+
signingRequest := kubeClient.CertificatesV1().CertificateSigningRequests()
163+
if _, err := signingRequest.UpdateApproval(context.TODO(), csr.Name, csr, metav1.UpdateOptions{}); err != nil {
164+
return false, err
165+
}
166+
167+
fmt.Printf("CSR %s approved\n", csr.Name)
168+
return true, nil
169+
}
134170

135-
mc, err := clusterClient.ClusterV1().ManagedClusters().Get(context.TODO(),
136-
clusterName,
137-
metav1.GetOptions{})
171+
func (o *Options) updateManagedCluster(clusterClient *clusterclientset.Clientset, clusterName string) (bool, error) {
172+
mc, err := clusterClient.ClusterV1().ManagedClusters().Get(context.TODO(),
173+
clusterName,
174+
metav1.GetOptions{})
175+
if err != nil {
176+
if errors.IsNotFound(err) {
177+
return false, nil
178+
}
179+
return false, err
180+
}
181+
if mc.Spec.HubAcceptsClient {
182+
fmt.Printf("httpAcceptsClient already set for cluster %s\n", clusterName)
183+
return true, nil
184+
}
185+
if o.ClusteradmFlags.DryRun {
186+
return true, nil
187+
}
188+
if !mc.Spec.HubAcceptsClient {
189+
mc.Spec.HubAcceptsClient = true
190+
_, err = clusterClient.ClusterV1().ManagedClusters().Update(context.TODO(), mc, metav1.UpdateOptions{})
138191
if err != nil {
139-
return err
192+
return false, err
140193
}
141-
if !mc.Spec.HubAcceptsClient {
142-
if !o.ClusteradmFlags.DryRun {
143-
mc.Spec.HubAcceptsClient = true
144-
_, err = clusterClient.ClusterV1().ManagedClusters().Update(context.TODO(), mc, metav1.UpdateOptions{})
145-
if err != nil {
146-
return err
147-
}
148-
}
149-
fmt.Printf("set httpAcceptsClient to true for cluster %s\n", clusterName)
150-
} else {
151-
fmt.Printf("httpAcceptsClient already set for cluster %s\n", clusterName)
194+
fmt.Printf("set httpAcceptsClient to true for cluster %s\n", clusterName)
195+
}
196+
return true, nil
197+
}
198+
199+
func GetCertApprovalCondition(status *certificatesv1.CertificateSigningRequestStatus) (approved bool, denied bool) {
200+
for _, c := range status.Conditions {
201+
if c.Type == certificatesv1.CertificateApproved {
202+
approved = true
203+
}
204+
if c.Type == certificatesv1.CertificateDenied {
205+
denied = true
152206
}
153207
}
154-
return nil
208+
return
155209
}

pkg/cmd/accept/options.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ type Options struct {
1111
ClusteradmFlags *genericclioptionsclusteradm.ClusteradmFlags
1212
//A list of comma separated cluster names
1313
clusters string
14-
values Values
14+
//Wait to wait in second for managedcluster and CSR
15+
wait int
16+
values Values
1517
}
1618

1719
//Values: The values used in the template

0 commit comments

Comments
 (0)