forked from fabric8io/kubernetes-client
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request fabric8io#2601 from adietish/issue-2599
- Loading branch information
Showing
5 changed files
with
819 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
248 changes: 248 additions & 0 deletions
248
...tes-client/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesVersionFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
/** | ||
* Copyright (C) 2015 Red Hat, Inc. | ||
* | ||
* 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 io.fabric8.kubernetes.client.utils; | ||
|
||
import java.util.Optional; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
/** | ||
* A factory that is creating a version instance for a given version string. | ||
* Returns {@link KubernetesVersion} instances for kubernetes versions (starts with 'v') | ||
* and {@link NonKubernetesVersion} otherwise. | ||
*/ | ||
public class KubernetesVersionFactory { | ||
|
||
private KubernetesVersionFactory() {} | ||
|
||
public static Version create(String versionValue) { | ||
Version version = KubernetesVersion.FACTORY.create(versionValue); | ||
if (version == null) { | ||
version = NonKubernetesVersion.FACTORY.create(versionValue); | ||
} | ||
return version; | ||
} | ||
|
||
public interface VersionFactory<T extends Version> { | ||
T create(String version); | ||
} | ||
|
||
/** | ||
* A kubernetes version. This represents a version that starts with a 'v' followed by a numerical major version. | ||
* Optionally this may be followed by an 'alpha' or 'beta' qualifier and an also optional numeric minor version. | ||
*/ | ||
public static class KubernetesVersion extends Version { | ||
|
||
public static final VersionFactory<KubernetesVersion> FACTORY = new VersionFactory<KubernetesVersion>() { | ||
|
||
private final Pattern versionPattern = Pattern.compile("v([0-9]+)((alpha|beta)([0-9]+)?)*"); | ||
|
||
@Override | ||
public KubernetesVersion create(String version) { | ||
if (version == null) { | ||
return null; | ||
} | ||
Matcher matcher = versionPattern.matcher(version); | ||
if (!matcher.matches()) { | ||
return null; | ||
} | ||
Integer majorValue = getInt(matcher.group(1)); | ||
String qualifierValue = matcher.group(3); | ||
Integer minorValue = getInt(matcher.group(4)); | ||
return new KubernetesVersion(majorValue, qualifierValue, minorValue, version); | ||
} | ||
|
||
private Integer getInt(String value) { | ||
if (value == null) { | ||
return null; | ||
} | ||
try { | ||
return Integer.parseInt(value); | ||
} catch(NumberFormatException e) { | ||
return null; | ||
} | ||
} | ||
}; | ||
|
||
private final Integer major; | ||
private final Optional<String> qualifier; | ||
private final Optional<Integer> minor; | ||
|
||
private KubernetesVersion(Integer major, String qualifier, Integer minor, String version) { | ||
super(version); | ||
this.major = major; | ||
this.qualifier = Optional.ofNullable(qualifier); | ||
this.minor = Optional.ofNullable(minor); | ||
} | ||
|
||
public Integer getMajor() { | ||
return major; | ||
} | ||
|
||
public Optional<String> getQualifier() { | ||
return qualifier; | ||
} | ||
|
||
public Optional<Integer> getMinor() { | ||
return minor; | ||
} | ||
|
||
public boolean isStable() { | ||
return qualifier.orElse(null) == null; | ||
} | ||
|
||
@Override | ||
public boolean isKubernetes() { | ||
return true; | ||
} | ||
|
||
/** | ||
* Compares this version to another version and returns whether this version has a | ||
* higher, equal or lower priority than the version that it is being compared to. | ||
* | ||
* The kubernetes specs v1.17 at <a href="https://v1-17.docs.kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definition-versioning/#version-priority">Version Priority</a> | ||
* state the following: | ||
* | ||
* <ul> | ||
* <li>Entries that follow Kubernetes version patterns are sorted before those that do not.</li> | ||
* <li>For entries that follow Kubernetes version patterns, the numeric portions of the version string is sorted largest to smallest.</li> | ||
* <li>If the strings beta or alpha follow the first numeric portion, they sorted in that order, after the equivalent string without the beta | ||
* or alpha suffix (which is presumed to be the GA version).</li> | ||
* <li>If another number follows the beta, or alpha, those numbers are also sorted from largest to smallest.</li> | ||
* <li>Strings that don’t fit the above format are sorted alphabetically and the numeric portions are not treated specially. Notice that in the example below, foo1 is sorted above foo10. | ||
* This is different from the sorting of the numeric portion of entries that do follow the Kubernetes version patterns.</li> | ||
* </ul> | ||
* | ||
* @param other the version to compare this version to | ||
* @return -1 if this version has a lower, 1 if it has a higher or 0 if the priorities are equal | ||
* | ||
*/ | ||
@Override | ||
public int compareTo(Version other) { | ||
if (other == this) { | ||
return 0; | ||
} | ||
if (other instanceof NonKubernetesVersion) { | ||
return 1; | ||
} | ||
if (!(other instanceof KubernetesVersion)) { | ||
return 1; | ||
} | ||
KubernetesVersion otherKube = (KubernetesVersion) other; | ||
if (qualifier.isPresent()) { | ||
if (!otherKube.qualifier.isPresent()) { | ||
return -1; | ||
} | ||
int qualifierComparison = qualifier.get().compareTo(otherKube.qualifier.orElse(null)); | ||
if (qualifierComparison != 0) { | ||
return qualifierComparison; | ||
} | ||
int majorComparison = compareMajor(otherKube); | ||
if (majorComparison != 0) { | ||
return majorComparison; | ||
} | ||
return compareMinor(otherKube); | ||
} else { | ||
if (!otherKube.qualifier.isPresent()) { | ||
return compareMajor(otherKube); | ||
} else { | ||
return 1; | ||
} | ||
} | ||
} | ||
|
||
private int compareMajor(KubernetesVersion other) { | ||
return major.compareTo(other.major); | ||
} | ||
|
||
private int compareMinor(KubernetesVersion other) { | ||
if (minor.isPresent()) { | ||
if (!other.minor.isPresent()) { | ||
return 1; | ||
} | ||
return minor.get().compareTo(other.minor.orElse(null)); | ||
} else { | ||
if (!other.minor.isPresent()) { | ||
return 0; | ||
} | ||
return -1; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* A non kubernetes version which is any version string that does not start with a 'v'. | ||
*/ | ||
public static class NonKubernetesVersion extends Version { | ||
|
||
public static final VersionFactory<NonKubernetesVersion> FACTORY = version -> { | ||
if (version == null) { | ||
return null; | ||
} | ||
return new NonKubernetesVersion(version); | ||
}; | ||
|
||
private NonKubernetesVersion(String version) { | ||
super(version); | ||
} | ||
|
||
@Override | ||
public boolean isKubernetes() { | ||
return false; | ||
} | ||
|
||
/** | ||
* Non-Kubernetes versions have lower priority than kubernetes versions. Among them they're inverse-lexicographically sorted. | ||
* | ||
* @param other the other version to compare to | ||
* @return -1 if this has a lower, 0 if equal or 1 if higher priority | ||
*/ | ||
@Override | ||
public int compareTo(Version other) { | ||
if (other == this) { | ||
return 0; | ||
} | ||
if (other instanceof KubernetesVersion) { | ||
return -1; | ||
} else if (other instanceof NonKubernetesVersion) { | ||
return full.compareTo(other.full) * -1; // inverse lexicographical order | ||
} else { | ||
return -1; | ||
} | ||
} | ||
} | ||
|
||
protected abstract static class Version implements Comparable<Version> { | ||
|
||
protected final String full; | ||
|
||
protected Version(String full) { | ||
this.full = full; | ||
} | ||
|
||
public abstract boolean isKubernetes(); | ||
|
||
public String getFull() { | ||
return full; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return full; | ||
} | ||
} | ||
|
||
} |
61 changes: 61 additions & 0 deletions
61
...es-client/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesVersionPriority.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/** | ||
* Copyright (C) 2015 Red Hat, Inc. | ||
* | ||
* 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 io.fabric8.kubernetes.client.utils; | ||
|
||
import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinitionSpec; | ||
import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinitionVersion; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
import static io.fabric8.kubernetes.client.utils.KubernetesVersionFactory.Version; | ||
|
||
/** | ||
* A util class that allows to deal with kubernetes versions. | ||
*/ | ||
public class KubernetesVersionPriority { | ||
|
||
private KubernetesVersionPriority() {} | ||
|
||
/** | ||
* Returns the version with the highest priority for the given list of versions. | ||
* | ||
* @param versions the versions to pick the version with the highest priority from | ||
* @return the version with the highest priority | ||
* | ||
* @see CustomResourceDefinitionVersion#getName() | ||
* @see CustomResourceDefinitionSpec#getVersions() | ||
*/ | ||
public static String highestPriority(List<String> versions) { | ||
List<Version> byPriority = getByPriority(versions); | ||
if (byPriority.isEmpty()) { | ||
return null; | ||
} | ||
return byPriority.get(0).getFull(); | ||
} | ||
|
||
private static List<Version> getByPriority(List<String> versions) { | ||
if (versions == null | ||
|| versions.isEmpty()) { | ||
return Collections.emptyList(); | ||
} | ||
return versions.stream() | ||
.map(KubernetesVersionFactory::create) | ||
.sorted(Collections.reverseOrder()) | ||
.collect(Collectors.toList()); | ||
} | ||
} |
Oops, something went wrong.