istio.io/istio@v0.0.0-20240520182934-d79c90f27776/operator/pkg/verifier/k8s_util.go (about) 1 // Copyright Istio Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package verifier 16 17 import ( 18 "fmt" 19 20 appsv1 "k8s.io/api/apps/v1" 21 v1batch "k8s.io/api/batch/v1" 22 apimachinery_schema "k8s.io/apimachinery/pkg/runtime/schema" 23 24 "istio.io/istio/pkg/config" 25 "istio.io/istio/pkg/config/schema/collections" 26 ) 27 28 func verifyDeploymentStatus(deployment *appsv1.Deployment) error { 29 cond := getDeploymentCondition(deployment.Status, appsv1.DeploymentProgressing) 30 if cond != nil && cond.Reason == "ProgressDeadlineExceeded" { 31 return fmt.Errorf("deployment %q exceeded its progress deadline", deployment.Name) 32 } 33 if deployment.Spec.Replicas != nil && deployment.Status.UpdatedReplicas < *deployment.Spec.Replicas { 34 return fmt.Errorf("waiting for deployment %q rollout to finish: %d out of %d new replicas have been updated", 35 deployment.Name, deployment.Status.UpdatedReplicas, *deployment.Spec.Replicas) 36 } 37 if deployment.Status.Replicas > deployment.Status.UpdatedReplicas { 38 return fmt.Errorf("waiting for deployment %q rollout to finish: %d old replicas are pending termination", 39 deployment.Name, deployment.Status.Replicas-deployment.Status.UpdatedReplicas) 40 } 41 if deployment.Status.AvailableReplicas < deployment.Status.UpdatedReplicas { 42 return fmt.Errorf("waiting for deployment %q rollout to finish: %d of %d updated replicas are available", 43 deployment.Name, deployment.Status.AvailableReplicas, deployment.Status.UpdatedReplicas) 44 } 45 return nil 46 } 47 48 func verifyDaemonSetStatus(daemonSet *appsv1.DaemonSet) error { 49 if daemonSet.Status.DesiredNumberScheduled != daemonSet.Status.CurrentNumberScheduled { 50 return fmt.Errorf("waiting for daemonset %s/%s rollout to finish: %d of %d desired pods are scheduled", 51 daemonSet.Namespace, daemonSet.Name, daemonSet.Status.CurrentNumberScheduled, daemonSet.Status.DesiredNumberScheduled) 52 } 53 switch daemonSet.Spec.UpdateStrategy.Type { 54 case appsv1.OnDeleteDaemonSetStrategyType: 55 if daemonSet.Status.UpdatedNumberScheduled != daemonSet.Status.DesiredNumberScheduled { 56 return fmt.Errorf("DaemonSet is not ready: %s/%s. %d out of %d expected pods have been scheduled", 57 daemonSet.Namespace, daemonSet.Name, daemonSet.Status.UpdatedNumberScheduled, daemonSet.Status.DesiredNumberScheduled) 58 } 59 case appsv1.RollingUpdateDaemonSetStrategyType: 60 if daemonSet.Status.DesiredNumberScheduled <= 0 { 61 return fmt.Errorf("DaemonSet %s/%s is not ready. Initializing, no pods are running", 62 daemonSet.Namespace, daemonSet.Name) 63 } else if daemonSet.Status.NumberReady < daemonSet.Status.DesiredNumberScheduled { 64 return fmt.Errorf("DaemonSet %s/%s is not ready. %d out of %d expected pods are ready", 65 daemonSet.Namespace, daemonSet.Name, daemonSet.Status.NumberReady, daemonSet.Status.DesiredNumberScheduled) 66 } 67 } 68 return nil 69 } 70 71 func getDeploymentCondition(status appsv1.DeploymentStatus, condType appsv1.DeploymentConditionType) *appsv1.DeploymentCondition { 72 for i := range status.Conditions { 73 c := status.Conditions[i] 74 if c.Type == condType { 75 return &c 76 } 77 } 78 return nil 79 } 80 81 func verifyJobPostInstall(job *v1batch.Job) error { 82 for _, c := range job.Status.Conditions { 83 if c.Type == v1batch.JobFailed { 84 return fmt.Errorf("the required Job %s/%s failed", job.Namespace, job.Name) 85 } 86 } 87 return nil 88 } 89 90 func findResourceInSpec(gvk apimachinery_schema.GroupVersionKind) string { 91 s, f := collections.All.FindByGroupVersionAliasesKind(config.GroupVersionKind{ 92 Group: gvk.Group, 93 Version: gvk.Version, 94 Kind: gvk.Kind, 95 }) 96 if !f { 97 return "" 98 } 99 return s.Plural() 100 }