-
Notifications
You must be signed in to change notification settings - Fork 220
Try to get lease namespace if unspecified #1450
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
Changes from all commits
b621d9d
1317c4f
cdd6fea
0c12947
014e05a
56a69be
87315bb
cdbe8d8
1204727
a2abd99
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,15 @@ public LeaderElectionConfiguration(String leaseName, String leaseNamespace) { | |
RETRY_PERIOD_DEFAULT_VALUE, null); | ||
} | ||
|
||
public LeaderElectionConfiguration(String leaseName) { | ||
this( | ||
leaseName, | ||
null, | ||
LEASE_DURATION_DEFAULT_VALUE, | ||
RENEW_DEADLINE_DEFAULT_VALUE, | ||
RETRY_PERIOD_DEFAULT_VALUE, null); | ||
} | ||
|
||
public LeaderElectionConfiguration( | ||
String leaseName, | ||
String leaseNamespace, | ||
|
@@ -59,8 +68,8 @@ public LeaderElectionConfiguration( | |
this.identity = identity; | ||
} | ||
|
||
public String getLeaseNamespace() { | ||
return leaseNamespace; | ||
public Optional<String> getLeaseNamespace() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: this is a breaking change. I can mark it as deprecated and provide another method There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahh normally I would prefer backwards compatible with deprecated. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably would be better, yes. Then again, I don't know if anyone is using Leader Election already… There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think for users, direct usage of this API will be rare even they do use leader election feature. Probably only in unit test. |
||
return Optional.ofNullable(leaseNamespace); | ||
} | ||
|
||
public String getLeaseName() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package io.javaoperatorsdk.operator; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
|
||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.io.TempDir; | ||
|
||
import io.fabric8.kubernetes.client.KubernetesClient; | ||
import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider; | ||
import io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration; | ||
|
||
import static io.fabric8.kubernetes.client.Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY; | ||
import static io.fabric8.kubernetes.client.Config.KUBERNETES_NAMESPACE_FILE; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
import static org.mockito.Mockito.mock; | ||
|
||
class LeaderElectionManagerTest { | ||
|
||
private ControllerManager controllerManager; | ||
private KubernetesClient kubernetesClient; | ||
private LeaderElectionManager leaderElectionManager; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
controllerManager = mock(ControllerManager.class); | ||
kubernetesClient = mock(KubernetesClient.class); | ||
leaderElectionManager = new LeaderElectionManager(controllerManager); | ||
} | ||
|
||
@AfterEach | ||
void tearDown() { | ||
ConfigurationServiceProvider.reset(); | ||
System.getProperties().remove(KUBERNETES_NAMESPACE_FILE); | ||
System.getProperties().remove(KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY); | ||
} | ||
|
||
@Test | ||
void testInit() { | ||
leaderElectionManager.init(new LeaderElectionConfiguration("test", "testns"), kubernetesClient); | ||
assertTrue(leaderElectionManager.isLeaderElectionEnabled()); | ||
} | ||
|
||
@Test | ||
void testInitInferLeaseNamespace(@TempDir Path tempDir) throws IOException { | ||
var namespace = "foo"; | ||
var namespacePath = tempDir.resolve("namespace"); | ||
Files.writeString(namespacePath, namespace); | ||
|
||
System.setProperty(KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you know why it's needed to set this property to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is because of https://github.com/fabric8io/kubernetes-client/blob/0742e942eb09f8ed2672f7f82e176b76e595ad50/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/Config.java#L600. Otherwise it will try to read There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm however still not sure this gets the correct client config. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The order also seems to be wrong: configurationService.getLeaderElectionConfiguration()
.ifPresent(c -> leaderElectionManager.init(c, this.kubernetesClient));
ConfigurationServiceProvider.set(configurationService); Now the PR as it is, tries to access For the use case creating k8s client manually, this seems to be required but maybe it is supposed to be so? var operator =
new Operator(
kubernetesClient,
configurationServiceOverrider ->
configurationServiceOverrider
.withCloseClientOnStop(false)
.withClientConfiguration(kubernetesClient.getConfiguration())); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, the instance is already set in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For example: var kubernetesClient = ...; # build the client; may not be from .kube/config
var operator =
new Operator(
kubernetesClient,
configurationServiceOverrider ->
configurationServiceOverrider
.withCloseClientOnStop(false)
.withClientConfiguration(kubernetesClient.getConfiguration())); If here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that is absolutely true. The thing is that on the other hand on quarkus extension it would make issues when the config from config service not used. Note however that if the namespace is configured for a client, it's not our api. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I understand that. I think as you said this is a separated issue to track, not related to leader election. I can create a new issue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I modified the existing e2e test a bit. PTAL, thanks. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We probably need to clean things up or, at the very least, document them better. The intention is to create client instance(s) based on the configuration retrieved from the |
||
System.setProperty(KUBERNETES_NAMESPACE_FILE, namespacePath.toString()); | ||
|
||
leaderElectionManager.init(new LeaderElectionConfiguration("test"), kubernetesClient); | ||
assertTrue(leaderElectionManager.isLeaderElectionEnabled()); | ||
} | ||
|
||
@Test | ||
void testFailedToInitInferLeaseNamespace() { | ||
System.setProperty(KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); | ||
assertThrows( | ||
IllegalArgumentException.class, | ||
() -> leaderElectionManager.init(new LeaderElectionConfiguration("test"), | ||
kubernetesClient)); | ||
} | ||
|
||
@Test | ||
void testFailedToInitInferLeaseNamespaceProbablyUsingKubeConfig() { | ||
assertThrows( | ||
IllegalArgumentException.class, | ||
() -> leaderElectionManager.init(new LeaderElectionConfiguration("test"), | ||
kubernetesClient)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
apiVersion: v1 | ||
kind: Pod | ||
metadata: | ||
name: leader-election-operator-2 | ||
spec: | ||
serviceAccountName: leader-election-operator | ||
containers: | ||
- name: operator | ||
image: leader-election-operator | ||
imagePullPolicy: Never | ||
env: | ||
- name: POD_NAME | ||
valueFrom: | ||
fieldRef: | ||
fieldPath: metadata.name |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
apiVersion: v1 | ||
kind: ServiceAccount | ||
metadata: | ||
name: leader-election-operator | ||
|
||
--- | ||
apiVersion: v1 | ||
kind: Pod | ||
metadata: | ||
name: leader-election-operator-1 | ||
spec: | ||
serviceAccountName: leader-election-operator | ||
containers: | ||
- name: operator | ||
image: leader-election-operator | ||
imagePullPolicy: Never | ||
env: | ||
- name: POD_NAME | ||
valueFrom: | ||
fieldRef: | ||
fieldPath: metadata.name | ||
|
||
--- | ||
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRoleBinding | ||
metadata: | ||
name: operator-admin | ||
subjects: | ||
- kind: ServiceAccount | ||
name: leader-election-operator | ||
roleRef: | ||
kind: ClusterRole | ||
name: leader-election-operator | ||
apiGroup: "" | ||
|
||
--- | ||
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRole | ||
metadata: | ||
name: leader-election-operator | ||
rules: | ||
- apiGroups: | ||
- "apiextensions.k8s.io" | ||
resources: | ||
- customresourcedefinitions | ||
verbs: | ||
- '*' | ||
- apiGroups: | ||
- "sample.javaoperatorsdk" | ||
resources: | ||
- leaderelectiontestcustomresources | ||
- leaderelectiontestcustomresources/status | ||
verbs: | ||
- '*' | ||
- apiGroups: | ||
- "coordination.k8s.io" | ||
resources: | ||
- "leases" | ||
verbs: | ||
- '*' |
Uh oh!
There was an error while loading. Please reload this page.