@@ -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}
0 commit comments