All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.fabric8.kubernetes.api.UserConfigurationCompare Maven / Gradle / Ivy

There is a newer version: 3.0.12
Show newest version
/**
 *  Copyright 2005-2016 Red Hat, Inc.
 *
 *  Red Hat licenses this file to you 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 io.fabric8.kubernetes.api;

import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.utils.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.validation.constraints.NotNull;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * Helper methods to compare the user configuration on entities
 */
public class UserConfigurationCompare {
    private static final transient Logger LOG = LoggerFactory.getLogger(UserConfigurationCompare.class);

    protected static final Set ignoredProperties = new HashSet<>(Collections.singletonList("status"));


    /**
     * This method detects if the user has changed the configuration of an entity.
     * 

* It compares the user configuration of 2 object trees ignoring any * runtime status or timestamp information. * * @return true if the configurations are equal. */ public static boolean configEqual(Object entity1, Object entity2) { if (entity1 == entity2) { return true; } else if (entity1 == null || entity2 == null) { return false; } else if (entity1 instanceof Map) { return configEqualMap((Map) entity1, castTo(Map.class, entity2)); } else if (entity2 instanceof Map) { return configEqualMap((Map) entity1, castTo(Map.class, entity2)); } else if (entity2 instanceof ObjectMeta) { return configEqualObjectMeta((ObjectMeta) entity1, castTo(ObjectMeta.class, entity2)); } else if (entity1 instanceof Collection && entity2 instanceof Collection) { return collectionsEqual((Collection) entity1, (Collection) entity2); } else { Class aClass = getCommonDenominator(entity1.getClass(), entity2.getClass()); if (aClass != null) { Object castEntity2 = castTo(aClass, entity2); if (castEntity2 == null) { return false; } else if (aClass.getPackage().getName().startsWith("io.fabric8")) { return configEqualKubernetesDTO(entity1, entity2, aClass); } } return Objects.equal(entity1, entity2); } } static boolean collectionsEqual(Collection left, Collection right) { return subCollection(left, right) && subCollection(right, left); } static boolean itemExists(L item, Collection collection) { for (R candidate : collection) { if (configEqual(item, candidate)) { return true; } } return false; } static boolean subCollection(Collection left, Collection right) { for (L candidate : left) { if (!itemExists(candidate, right)) { return false; } } return true; } static Class getCommonDenominator(Class left, Class right) { if (left.equals(right)) { return left; } else if (left.isAssignableFrom(right)) { return getCommonDenominator(left, right.getSuperclass()); } else if (right.isAssignableFrom(left)) { return getCommonDenominator(left.getSuperclass(), right); } else { //no match return null; } } /** * Compares 2 instances of the given Kubernetes DTO class to see if the user has changed their configuration. *

* This method will ignore properties {@link #ignoredProperties} such as status or timestamp properties */ protected static boolean configEqualKubernetesDTO(@NotNull Object entity1, @NotNull Object entity2, @NotNull Class clazz) { // lets iterate through the objects making sure we've not BeanInfo beanInfo = null; try { beanInfo = Introspector.getBeanInfo(clazz); } catch (IntrospectionException e) { LOG.warn("Failed to get beanInfo for " + clazz.getName() + ". " + e, e); return false; } try { PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { String name = propertyDescriptor.getName(); if (ignoredProperties.contains(name)) { continue; } Method readMethod = propertyDescriptor.getReadMethod(); if (readMethod != null) { Object value1 = invokeMethod(entity1, readMethod); Object value2 = invokeMethod(entity2, readMethod); if (!configEqual(value1, value2)) { return false; } } } return true; } catch (Exception e) { return false; } } protected static Object invokeMethod(@NotNull Object entity, Method readMethod) throws InvocationTargetException, IllegalAccessException { try { return readMethod.invoke(entity); } catch (Exception e) { LOG.warn("Failed to invoke method " + readMethod + " on " + entity + ". " + e, e); throw e; } } protected static boolean configEqualObjectMeta(ObjectMeta entity1, ObjectMeta entity2) { if (entity1 == entity2) { return true; } else if (entity1 == null || entity2 == null) { return false; } // TODO should we ignore annotations? return Objects.equal(entity1.getName(), entity2.getName()) && Objects.equal(entity1.getNamespace(), entity2.getNamespace()) && configEqualMap(entity1.getLabels(), entity2.getLabels()) && configEqualMap(entity1.getAnnotations(), entity2.getAnnotations()); } protected static T castTo(Class clazz, Object entity) { if (clazz.isInstance(entity)) { return clazz.cast(entity); } else { if (entity != null) { LOG.warn("Invalid class " + entity.getClass().getName() + " when expecting " + clazz.getName() + " for instance: " + entity); } return null; } } protected static boolean configEqualMap(Map entity1, Map entity2) { if (entity1 == entity2) { return true; } else if (entity1 == null || entity2 == null) { return false; } int size1 = size(entity1); int size2 = size(entity2); if (size1 != size2) { return false; } Set entries = entity1.entrySet(); for (Map.Entry entry : entries) { Object key = entry.getKey(); Object value = entry.getValue(); Object value2 = entity2.get(key); if (!configEqual(value, value2)) { return false; } } return true; } protected static boolean configEqualList(List v1, List v2) { int size1 = size(v1); int size2 = size(v2); if (size1 != size2) { return false; } int idx = 0; for (Object value : v1) { Object value2 = v2.get(idx++); if (!configEqual(value, value2)) { return false; } } return true; } protected static int size(Map map) { return (map == null) ? 0 : map.size(); } protected static int size(Collection coll) { return (coll == null) ? 0 : coll.size(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy