Skip to content

Update config maps based on hash like other resources #2321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 23, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Tests passing
  • Loading branch information
rjeberhard committed Apr 16, 2021
commit 61e49a47042a1161fee8560031b72c9ad65d92a2
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ private ConfigMapHelper() {
* Factory for {@link Step} that creates config map containing scripts.
*
* @param domainNamespace the domain's namespace
* @param productVersion Operator version
* @return Step for creating config map containing scripts
*/
public static Step createScriptConfigMapStep(String domainNamespace, SemanticVersion productVersion) {
Expand Down Expand Up @@ -164,8 +163,16 @@ public static String getIntrospectorConfigMapName(String domainUid) {
}

abstract static class ConfigMapComparator {
boolean containsAll(V1ConfigMap actual, V1ConfigMap expected) {
return containsAllData(getData(actual), getData(expected));
boolean isOutdated(SemanticVersion productVersion, V1ConfigMap actual, V1ConfigMap expected) {
// Check product version label
if (productVersion != null) {
SemanticVersion currentVersion = KubernetesUtils.getProductVersionFromMetadata(actual.getMetadata());
if (currentVersion == null || productVersion.compareTo(currentVersion) > 0) {
return true;
}
}

return !AnnotationHelper.getHash(expected).equals(AnnotationHelper.getHash(actual));
}

private Map<String,String> getData(V1ConfigMap map) {
Expand All @@ -189,26 +196,23 @@ public NextAction apply(Packet packet) {
}

static class ScriptConfigMapContext extends ConfigMapContext {

ScriptConfigMapContext(Step conflictStep, String domainNamespace, SemanticVersion productVersion) {
super(conflictStep, SCRIPT_CONFIG_MAP_NAME, domainNamespace,
loadScriptsFromClasspath(domainNamespace), null, productVersion);

addLabel(LabelConstants.OPERATORNAME_LABEL, getOperatorNamespace());
}

private static synchronized Map<String, String> loadScriptsFromClasspath(String domainNamespace) {
Map<String, String> scripts = scriptReader.loadFilesFromClasspath();
LOGGER.fine(MessageKeys.SCRIPT_LOADED, domainNamespace);
return scripts;
}

@Override
void recordCurrentMap(Packet packet, V1ConfigMap configMap) {
packet.put(ProcessingConstants.SCRIPT_CONFIG_MAP, configMap);
}
}


static synchronized Map<String, String> loadScriptsFromClasspath(String domainNamespace) {
Map<String, String> scripts = scriptReader.loadFilesFromClasspath();
LOGGER.fine(MessageKeys.SCRIPT_LOADED, domainNamespace);
return scripts;
}

abstract static class ConfigMapContext extends StepContextBase {
Expand All @@ -218,7 +222,7 @@ abstract static class ConfigMapContext extends StepContextBase {
private final String namespace;
private V1ConfigMap model;
private final Map<String, String> labels = new HashMap<>();
private final SemanticVersion productVersion;
protected final SemanticVersion productVersion;

ConfigMapContext(Step conflictStep, String name, String namespace, Map<String, String> contents,
DomainPresenceInfo info, SemanticVersion productVersion) {
Expand Down Expand Up @@ -257,15 +261,22 @@ protected V1ConfigMap getModel() {
}

protected final V1ConfigMap createModel(Map<String, String> data) {
return new V1ConfigMap().kind("ConfigMap").apiVersion("v1").metadata(createMetadata()).data(data);
return AnnotationHelper.withSha256Hash(
new V1ConfigMap().kind("ConfigMap").apiVersion("v1").metadata(createMetadata()).data(data), data);
}

private V1ObjectMeta createMetadata() {
return updateForOwnerReference(
V1ObjectMeta metadata = updateForOwnerReference(
new V1ObjectMeta()
.name(name)
.namespace(namespace)
.labels(labels));

if (productVersion != null) {
metadata.putLabelsItem(LabelConstants.OPERATOR_VERSION, productVersion.toString());
}

return metadata;
}

@SuppressWarnings("SameParameterValue")
Expand All @@ -287,8 +298,8 @@ Step verifyConfigMap(Step next) {
return new CallBuilder().readConfigMapAsync(getName(), namespace, null, new ReadResponseStep(next));
}

boolean isIncompatibleMap(V1ConfigMap existingMap) {
return !COMPARATOR.containsAll(existingMap, getModel());
boolean isOutdated(V1ConfigMap existingMap) {
return COMPARATOR.isOutdated(productVersion, existingMap, getModel());
}

V1ConfigMap withoutTransientData(V1ConfigMap originalMap) {
Expand Down Expand Up @@ -319,8 +330,8 @@ public NextAction onSuccess(Packet packet, CallResponse<V1ConfigMap> callRespons
V1ConfigMap existingMap = withoutTransientData(callResponse.getResult());
if (existingMap == null) {
return doNext(createConfigMap(getNext()), packet);
} else if (isIncompatibleMap(existingMap)) {
return doNext(updateConfigMap(getNext(), existingMap), packet);
} else if (isOutdated(existingMap)) {
return doNext(replaceConfigMap(getNext()), packet);
} else if (mustPatchCurrentMap(existingMap)) {
return doNext(patchCurrentMap(existingMap, getNext()), packet);
} else {
Expand All @@ -339,9 +350,9 @@ private void logConfigMapExists() {
LOGGER.fine(MessageKeys.CM_EXISTS, getName(), namespace);
}

private Step updateConfigMap(Step next, V1ConfigMap existingConfigMap) {
private Step replaceConfigMap(Step next) {
return new CallBuilder().replaceConfigMapAsync(name, namespace,
createModel(getCombinedData(existingConfigMap)),
model,
createReplaceResponseStep(next));
}

Expand Down Expand Up @@ -374,12 +385,6 @@ private boolean labelsNotDefined(V1ConfigMap currentMap) {
}
}

private Map<String, String> getCombinedData(V1ConfigMap existingConfigMap) {
Map<String, String> updated = Objects.requireNonNull(existingConfigMap.getData());
updated.putAll(contents);
return updated;
}

private ResponseStep<V1ConfigMap> createCreateResponseStep(Step next) {
return new CreateResponseStep(next);
}
Expand Down Expand Up @@ -698,8 +703,8 @@ IntrospectorConfigMapContext patchOnly() {
}

@Override
boolean isIncompatibleMap(V1ConfigMap existingMap) {
return !patchOnly && super.isIncompatibleMap(existingMap);
boolean isOutdated(V1ConfigMap existingMap) {
return !patchOnly && super.isOutdated(existingMap);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -698,7 +697,7 @@ public boolean isOutdatedCrd(SemanticVersion productVersion,

// Check product version label
if (productVersion != null) {
SemanticVersion currentCrdVersion = getProductVersionFromMetadata(actual.getMetadata());
SemanticVersion currentCrdVersion = KubernetesUtils.getProductVersionFromMetadata(actual.getMetadata());
if (currentCrdVersion == null || productVersion.compareTo(currentCrdVersion) < 0) {
return false;
}
Expand All @@ -721,7 +720,7 @@ public boolean isOutdatedBetaCrd(SemanticVersion productVersion,

// Check product version label
if (productVersion != null) {
SemanticVersion currentCrdVersion = getProductVersionFromMetadata(actual.getMetadata());
SemanticVersion currentCrdVersion = KubernetesUtils.getProductVersionFromMetadata(actual.getMetadata());
if (currentCrdVersion == null || productVersion.compareTo(currentCrdVersion) < 0) {
return false;
}
Expand All @@ -730,14 +729,6 @@ public boolean isOutdatedBetaCrd(SemanticVersion productVersion,
return !AnnotationHelper.getHash(expected).equals(AnnotationHelper.getHash(actual));
}

private SemanticVersion getProductVersionFromMetadata(V1ObjectMeta metadata) {
return Optional.ofNullable(metadata)
.map(V1ObjectMeta::getLabels)
.map(labels -> labels.get(LabelConstants.OPERATOR_VERSION))
.map(SemanticVersion::new)
.orElse(null);
}

// true, if version is later than base
private boolean isLaterOrEqual(ResourceVersion base, ResourceVersion version) {
if (!version.getVersion().equals(base.getVersion())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,17 @@ public static String getInferredImagePullPolicy(String imageName) {
private static boolean useLatestImage(String imageName) {
return imageName.endsWith(KubernetesConstants.LATEST_IMAGE_SUFFIX);
}

/**
* Reads operator product version that created a resource, if available.
* @param metadata Metadata from a resource
* @return Operator product version that created the resource
*/
public static SemanticVersion getProductVersionFromMetadata(V1ObjectMeta metadata) {
return Optional.ofNullable(metadata)
.map(V1ObjectMeta::getLabels)
.map(labels -> labels.get(LabelConstants.OPERATOR_VERSION))
.map(SemanticVersion::new)
.orElse(null);
}
}
Loading