org.apache.kafka.image.ScramDelta Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 org.apache.kafka.image;
import org.apache.kafka.clients.admin.ScramMechanism;
import org.apache.kafka.common.metadata.RemoveUserScramCredentialRecord;
import org.apache.kafka.common.metadata.UserScramCredentialRecord;
import org.apache.kafka.server.common.MetadataVersion;
import org.apache.kafka.metadata.ScramCredentialData;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Map;
import java.util.Optional;
/**
* Represents changes to a topic in the metadata image.
*/
public final class ScramDelta {
private final ScramImage image;
private final Map>> changes = new HashMap<>();
public ScramDelta(ScramImage image) {
this.image = image;
}
public void finishSnapshot() {
for (Entry> mechanismEntry : image.mechanisms().entrySet()) {
Map> userNameMap =
changes.computeIfAbsent(mechanismEntry.getKey(), __ -> new HashMap<>());
for (String userName : mechanismEntry.getValue().keySet()) {
if (!userNameMap.containsKey(userName)) {
userNameMap.put(userName, Optional.empty());
}
}
}
}
public ScramImage image() {
return image;
}
public Map>> changes() {
return changes;
}
public void replay(UserScramCredentialRecord record) {
ScramMechanism mechanism = ScramMechanism.fromType(record.mechanism());
Map> userChanges =
changes.computeIfAbsent(mechanism, __ -> new HashMap<>());
userChanges.put(record.name(), Optional.of(ScramCredentialData.fromRecord(record)));
}
public void replay(RemoveUserScramCredentialRecord record) {
ScramMechanism mechanism = ScramMechanism.fromType(record.mechanism());
Map> userChanges =
changes.computeIfAbsent(mechanism, __ -> new HashMap<>());
userChanges.put(record.name(), Optional.empty());
}
public void handleMetadataVersionChange(MetadataVersion changedMetadataVersion) {
// nothing to do
}
public ScramImage apply() {
Map> newMechanisms = new HashMap<>();
for (Entry> mechanismEntry : image.mechanisms().entrySet()) {
newMechanisms.put(mechanismEntry.getKey(), new HashMap<>(mechanismEntry.getValue()));
}
for (Entry>> mechanismChangeEntry : changes.entrySet()) {
Map userMap =
newMechanisms.computeIfAbsent(mechanismChangeEntry.getKey(), __ -> new HashMap<>());
for (Entry> userNameEntry : mechanismChangeEntry.getValue().entrySet()) {
if (userNameEntry.getValue().isPresent()) {
userMap.put(userNameEntry.getKey(), userNameEntry.getValue().get());
} else {
userMap.remove(userNameEntry.getKey());
if (userMap.isEmpty()) {
newMechanisms.remove(mechanismChangeEntry.getKey());
}
}
}
}
return new ScramImage(newMechanisms);
}
@Override
public String toString() {
return "ScramDelta(" +
"changes=" + changes +
')';
}
}