forked from rook/rook
Merge pull request #17739 from rook/mergify/bp/release-1.20/pr-17726
k8sutil: remove unused helper functions (backport #17726)
This commit is contained in:
@@ -17,13 +17,6 @@ limitations under the License.
|
||||
// Package kit for Kubernetes operators
|
||||
package k8sutil
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// CustomResource is for creating a Kubernetes TPR/CRD
|
||||
type CustomResource struct {
|
||||
// Name of the custom resource
|
||||
@@ -44,18 +37,3 @@ type CustomResource struct {
|
||||
// APIVersion is the full API version name (combine Group and Version)
|
||||
APIVersion string
|
||||
}
|
||||
|
||||
// WatchCR begins watching the custom resource (CRD). The call will block until a Done signal is raised during in the context.
|
||||
// When the watch has detected a create, update, or delete event, it will handled by the functions in the resourceEventHandlers. After the callback returns, the watch loop will continue for the next event.
|
||||
// If the callback returns an error, the error will be logged.
|
||||
func WatchCR(resource CustomResource, namespace string, handlers cache.ResourceEventHandlerFuncs, client rest.Interface, objType runtime.Object, done <-chan struct{}) {
|
||||
source := cache.NewListWatchFromClient(
|
||||
client,
|
||||
resource.Plural,
|
||||
namespace,
|
||||
fields.Everything())
|
||||
_, controller := cache.NewInformerWithOptions(cache.InformerOptions{ListerWatcher: source, ObjectType: objType, ResyncPeriod: 0, Handler: handlers})
|
||||
|
||||
go controller.Run(done)
|
||||
<-done
|
||||
}
|
||||
|
||||
@@ -424,44 +424,6 @@ func GetDeploymentOwnerReference(ctx context.Context, clientset kubernetes.Inter
|
||||
return deploymentRef, nil
|
||||
}
|
||||
|
||||
// WaitForDeploymentImage waits for all deployments with the given labels are running.
|
||||
// WARNING:This is currently only useful for testing!
|
||||
func WaitForDeploymentImage(ctx context.Context, clientset kubernetes.Interface, namespace, label, container string, initContainer bool, desiredImage string) error {
|
||||
sleepTime := 3
|
||||
attempts := 120
|
||||
for i := 0; i < attempts; i++ {
|
||||
deployments, err := clientset.AppsV1().Deployments(namespace).List(ctx, metav1.ListOptions{LabelSelector: label})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list deployments with label %s. %v", label, err)
|
||||
}
|
||||
|
||||
matches := 0
|
||||
for _, d := range deployments.Items {
|
||||
image, err := GetDeploymentSpecImage(clientset, d, container, initContainer)
|
||||
if err != nil {
|
||||
logger.Infof("failed to get image for deployment %s. %+v", d.Name, err)
|
||||
continue
|
||||
}
|
||||
if image == desiredImage {
|
||||
matches++
|
||||
}
|
||||
}
|
||||
|
||||
if matches == len(deployments.Items) && matches > 0 {
|
||||
logger.Infof("all %d %s deployments are on image %s", matches, label, desiredImage)
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(deployments.Items) == 0 {
|
||||
logger.Infof("waiting for at least one deployment to start to see the version")
|
||||
} else {
|
||||
logger.Infof("%d/%d %s deployments match image %s", matches, len(deployments.Items), label, desiredImage)
|
||||
}
|
||||
time.Sleep(time.Duration(sleepTime) * time.Second)
|
||||
}
|
||||
return fmt.Errorf("failed to wait for image %s in label %s", desiredImage, label)
|
||||
}
|
||||
|
||||
// AddRookVersionLabelToDeployment adds or updates a label reporting the Rook version which last
|
||||
// modified a deployment.
|
||||
func AddRookVersionLabelToDeployment(d *appsv1.Deployment) {
|
||||
|
||||
@@ -25,7 +25,6 @@ import (
|
||||
batch "k8s.io/api/batch/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
@@ -58,32 +57,6 @@ func RunReplaceableJob(ctx context.Context, clientset kubernetes.Interface, job
|
||||
return err
|
||||
}
|
||||
|
||||
// WaitForJobCompletion waits for a job to reach the completed state.
|
||||
// Assumes that only one pod needs to complete.
|
||||
func WaitForJobCompletion(ctx context.Context, clientset kubernetes.Interface, job *batch.Job, timeout time.Duration) error {
|
||||
logger.Infof("waiting for job %s to complete...", job.Name)
|
||||
return wait.PollUntilContextTimeout(ctx, 5*time.Second, timeout, true, func(context context.Context) (bool, error) {
|
||||
job, err := clientset.BatchV1().Jobs(job.Namespace).Get(ctx, job.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to detect job %s. %+v", job.Name, err)
|
||||
}
|
||||
|
||||
// if the job is still running, allow it to continue to completion
|
||||
if job.Status.Active > 0 {
|
||||
logger.Debugf("job is still running. Status=%+v", job.Status)
|
||||
return false, nil
|
||||
}
|
||||
if job.Status.Failed > 0 {
|
||||
return false, fmt.Errorf("job %s failed", job.Name)
|
||||
}
|
||||
if job.Status.Succeeded > 0 {
|
||||
return true, nil
|
||||
}
|
||||
logger.Debugf("job is still initializing")
|
||||
return false, nil
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteBatchJob deletes a Kubernetes job.
|
||||
func DeleteBatchJob(ctx context.Context, clientset kubernetes.Interface, namespace, name string, wait bool) error {
|
||||
propagation := metav1.DeletePropagationForeground
|
||||
|
||||
@@ -30,8 +30,6 @@ import (
|
||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
var logger = capnslog.NewPackageLogger("github.com/rook/rook", "op-k8sutil")
|
||||
@@ -60,23 +58,6 @@ const (
|
||||
DefaultServiceAccount = "rook-ceph-default"
|
||||
)
|
||||
|
||||
// GetK8SVersion gets the version of the running K8S cluster
|
||||
func GetK8SVersion(clientset kubernetes.Interface) (*version.Version, error) {
|
||||
serverVersion, err := clientset.Discovery().ServerVersion()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting server version: %v", err)
|
||||
}
|
||||
|
||||
// make sure the kubernetes version is parseable
|
||||
index := strings.Index(serverVersion.GitVersion, "+")
|
||||
if index != -1 {
|
||||
newVersion := serverVersion.GitVersion[:index]
|
||||
logger.Debugf("returning version %s instead of %s", newVersion, serverVersion.GitVersion)
|
||||
serverVersion.GitVersion = newVersion
|
||||
}
|
||||
return version.MustParseSemantic(serverVersion.GitVersion), nil
|
||||
}
|
||||
|
||||
// Hash stableName computes a stable pseudorandom string suitable for inclusion in a Kubernetes object name from the given seed string.
|
||||
// Do **NOT** edit this function in a way that would change its output as it needs to
|
||||
// provide consistent mappings from string to hash across versions of rook.
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
Copyright 2020 The Rook Authors. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package k8sutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
kerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// Patcher is a utility for patching of objects and their status.
|
||||
// Portion of this file is coming from https://github.com/kubernetes-sigs/cluster-api/blob/master/util/patch/patch.go
|
||||
type Patcher struct {
|
||||
client client.Client
|
||||
hasStatus bool
|
||||
old map[string]interface{}
|
||||
oldStatus interface{}
|
||||
objectPatch client.Patch
|
||||
statusPatch client.Patch
|
||||
}
|
||||
|
||||
func NewPatcher(object client.Object, crclient client.Client) (*Patcher, error) {
|
||||
if object == nil {
|
||||
return nil, errors.Errorf("expected non-nil resource")
|
||||
}
|
||||
|
||||
if _, ok := object.(runtime.Unstructured); ok {
|
||||
object = object.DeepCopyObject().(client.Object)
|
||||
}
|
||||
|
||||
old, err := runtime.DefaultUnstructuredConverter.ToUnstructured(object)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hasStatus := false
|
||||
oldStatus, ok, err := unstructured.NestedFieldCopy(old, "status")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ok {
|
||||
hasStatus = true
|
||||
unstructured.RemoveNestedField(old, "status")
|
||||
}
|
||||
|
||||
return &Patcher{
|
||||
client: crclient,
|
||||
hasStatus: hasStatus,
|
||||
old: old,
|
||||
oldStatus: oldStatus,
|
||||
objectPatch: client.MergeFrom(object.DeepCopyObject().(client.Object)),
|
||||
statusPatch: client.MergeFrom(object.DeepCopyObject().(client.Object)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *Patcher) Patch(ctx context.Context, object client.Object) error {
|
||||
if object == nil {
|
||||
return errors.Errorf("expected non-nil resource")
|
||||
}
|
||||
|
||||
newObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hasStatus := false
|
||||
newStatus, ok, err := unstructured.NestedFieldCopy(newObj, "status")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ok {
|
||||
hasStatus = true
|
||||
unstructured.RemoveNestedField(newObj, "status")
|
||||
}
|
||||
|
||||
var errs []error
|
||||
if !reflect.DeepEqual(p.old, newObj) {
|
||||
if err := p.client.Patch(ctx, object, p.objectPatch); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
if (p.hasStatus || hasStatus) && !reflect.DeepEqual(p.oldStatus, newStatus) {
|
||||
if err := p.client.Status().Patch(ctx, object, p.statusPatch); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
return kerrors.NewAggregate(errs)
|
||||
}
|
||||
@@ -20,11 +20,9 @@ package k8sutil
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rook/rook/pkg/clusterd"
|
||||
@@ -53,18 +51,6 @@ const (
|
||||
ObservedGenerationNotAvailable int64 = -1
|
||||
)
|
||||
|
||||
// ConfigOverrideMount is an override mount
|
||||
func ConfigOverrideMount() v1.VolumeMount {
|
||||
return v1.VolumeMount{Name: ConfigOverrideName, MountPath: configMountDir}
|
||||
}
|
||||
|
||||
// ConfigOverrideVolume is an override volume
|
||||
func ConfigOverrideVolume() v1.Volume {
|
||||
cmSource := &v1.ConfigMapVolumeSource{Items: []v1.KeyToPath{{Key: ConfigOverrideVal, Path: overrideFilename}}}
|
||||
cmSource.Name = ConfigOverrideName
|
||||
return v1.Volume{Name: ConfigOverrideName, VolumeSource: v1.VolumeSource{ConfigMap: cmSource}}
|
||||
}
|
||||
|
||||
// ConfigOverrideEnvVar config override env var
|
||||
func ConfigOverrideEnvVar() v1.EnvVar {
|
||||
return v1.EnvVar{Name: "ROOK_CEPH_CONFIG_OVERRIDE", Value: path.Join(configMountDir, overrideFilename)}
|
||||
@@ -233,35 +219,6 @@ func GetPodPhaseMap(pods *v1.PodList) map[v1.PodPhase][]string {
|
||||
return podPhaseMap
|
||||
}
|
||||
|
||||
// GetJobLog gets the logs for the pod. If there is more than one pod with the label selector, the logs from
|
||||
// the first pod will be returned.
|
||||
func GetPodLog(ctx context.Context, clientset kubernetes.Interface, namespace string, labelSelector string) (string, error) {
|
||||
opts := metav1.ListOptions{
|
||||
LabelSelector: labelSelector,
|
||||
}
|
||||
pods, err := clientset.CoreV1().Pods(namespace).List(ctx, opts)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get version pod. %+v", err)
|
||||
}
|
||||
for _, pod := range pods.Items {
|
||||
req := clientset.CoreV1().Pods(namespace).GetLogs(pod.Name, &v1.PodLogOptions{})
|
||||
readCloser, err := req.Stream(ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read from stream. %+v", err)
|
||||
}
|
||||
|
||||
builder := &strings.Builder{}
|
||||
defer readCloser.Close()
|
||||
_, err = io.Copy(builder, readCloser)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "error copying file from %s to %s", builder, readCloser)
|
||||
}
|
||||
return builder.String(), err //nolint // no else statement needed
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("did not find any pods with label %s", labelSelector)
|
||||
}
|
||||
|
||||
// ClusterDaemonEnvVars Environment variables used by storage cluster daemon
|
||||
func ClusterDaemonEnvVars(image string) []v1.EnvVar {
|
||||
return []v1.EnvVar{
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
|
||||
monitoringclient "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned"
|
||||
"github.com/rook/rook/pkg/clusterd"
|
||||
@@ -104,25 +103,3 @@ func CreateOrUpdateServiceMonitor(context *clusterd.Context, ctx context.Context
|
||||
}
|
||||
return sm, nil
|
||||
}
|
||||
|
||||
// DeleteServiceMonitor deletes a ServiceMonitor and returns the error if any
|
||||
func DeleteServiceMonitor(context *clusterd.Context, ctx context.Context, ns string, name string) error {
|
||||
client, err := getMonitoringClient(context)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get monitoring client. %v", err)
|
||||
}
|
||||
_, err = client.MonitoringV1().ServiceMonitors(ns).Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
// Either the service monitor does not exist or there are no privileges to detect it
|
||||
// so we ignore any errors
|
||||
return nil
|
||||
}
|
||||
err = client.MonitoringV1().ServiceMonitors(ns).Delete(ctx, name, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
if kerrors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrapf(err, "failed to delete service monitor %q", name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Rook Authors. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package k8sutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// DeleteReplicaSet makes a best effort at deleting a deployment and its pods, then waits for them to be deleted
|
||||
func DeleteReplicaSet(ctx context.Context, clientset kubernetes.Interface, namespace, name string) error {
|
||||
deleteAction := func(options *metav1.DeleteOptions) error {
|
||||
return clientset.AppsV1().ReplicaSets(namespace).Delete(ctx, name, *options)
|
||||
}
|
||||
getAction := func() error {
|
||||
_, err := clientset.AppsV1().ReplicaSets(namespace).Get(ctx, name, metav1.GetOptions{})
|
||||
return err
|
||||
}
|
||||
return deleteResourceAndWait(namespace, name, "replicaset", deleteAction, getAction)
|
||||
}
|
||||
@@ -72,17 +72,6 @@ func UpdateService(
|
||||
return clientset.CoreV1().Services(namespace).Update(ctx, serviceDefinition, metav1.UpdateOptions{})
|
||||
}
|
||||
|
||||
// DeleteService deletes a Service and returns the error if any
|
||||
func DeleteService(ctx context.Context, clientset kubernetes.Interface, namespace, name string) error {
|
||||
err := clientset.CoreV1().Services(namespace).Delete(ctx, name, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
if kerrors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// ParseServiceType parses a string and returns a*v1.ServiceType. If the ServiceType is invalid,
|
||||
// this should be considered an error.
|
||||
func ParseServiceType(serviceString string) v1.ServiceType {
|
||||
|
||||
@@ -18,18 +18,10 @@ limitations under the License.
|
||||
package k8sutil
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/yaml"
|
||||
)
|
||||
|
||||
const (
|
||||
BinariesMountPath = "/rook"
|
||||
)
|
||||
|
||||
// PathToVolumeName converts a path to a valid volume name
|
||||
@@ -72,64 +64,3 @@ func PathToVolumeName(path string) string {
|
||||
|
||||
return volumeName
|
||||
}
|
||||
|
||||
// NodeConfigURI returns the node config URI path for this node
|
||||
func NodeConfigURI() (string, error) {
|
||||
nodeName := os.Getenv(NodeNameEnvVar)
|
||||
if nodeName == "" {
|
||||
return "", fmt.Errorf("cannot detect the node name. Please provide using the downward API in the rook operator manifest file")
|
||||
}
|
||||
return fmt.Sprintf("api/v1/nodes/%s/proxy/configz", nodeName), nil
|
||||
}
|
||||
|
||||
func BinariesMountInfo() (v1.EnvVar, v1.Volume, v1.VolumeMount) {
|
||||
// To get rook inside the container, the config init container needs to copy "rook" binary into a volume.
|
||||
// Set the config flag so rook will copy the binaries.
|
||||
// Create the volume and mount that will be shared between the init container and the daemon container
|
||||
volumeName := "rookbinaries"
|
||||
e := v1.EnvVar{Name: "ROOK_COPY_BINARIES_PATH", Value: BinariesMountPath}
|
||||
v := v1.Volume{Name: volumeName, VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}}}
|
||||
m := v1.VolumeMount{Name: volumeName, MountPath: BinariesMountPath}
|
||||
return e, v, m
|
||||
}
|
||||
|
||||
// This function takes raw YAML string and converts it to Kubernetes Volume array.
|
||||
func YamlToVolumes(raw string) ([]v1.Volume, error) {
|
||||
if raw == "" {
|
||||
return []v1.Volume{}, nil
|
||||
}
|
||||
|
||||
rawJSON, err := yaml.ToJSON([]byte(raw))
|
||||
if err != nil {
|
||||
return []v1.Volume{}, err
|
||||
}
|
||||
|
||||
var volume []v1.Volume
|
||||
err = json.Unmarshal(rawJSON, &volume)
|
||||
if err != nil {
|
||||
return []v1.Volume{}, err
|
||||
}
|
||||
|
||||
return volume, nil
|
||||
}
|
||||
|
||||
// This function takes raw YAML string and converts it to Kubernetes Volume
|
||||
// mount array.
|
||||
func YamlToVolumeMounts(raw string) ([]v1.VolumeMount, error) {
|
||||
if raw == "" {
|
||||
return []v1.VolumeMount{}, nil
|
||||
}
|
||||
|
||||
rawJSON, err := yaml.ToJSON([]byte(raw))
|
||||
if err != nil {
|
||||
return []v1.VolumeMount{}, err
|
||||
}
|
||||
|
||||
var volumeMount []v1.VolumeMount
|
||||
err = json.Unmarshal(rawJSON, &volumeMount)
|
||||
if err != nil {
|
||||
return []v1.VolumeMount{}, err
|
||||
}
|
||||
|
||||
return volumeMount, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user