Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • May 12 19:37
    sonarcloud[bot] commented #3108
  • May 12 19:37
    sonarcloud[bot] commented #3108
  • May 12 19:18
    sonarcloud[bot] commented #3108
  • May 12 19:18
    sonarcloud[bot] commented #3108
  • May 12 19:08
    shawkins synchronize #3108
  • May 12 19:00
    sonarcloud[bot] commented #3108
  • May 12 19:00
    sonarcloud[bot] commented #3108
  • May 12 18:59
    sonarcloud[bot] commented #3108
  • May 12 18:49
    shawkins synchronize #3108
  • May 12 18:36
    shawkins synchronize #3108
  • May 12 18:35
    shawkins synchronize #3108
  • May 12 17:41
    sonarcloud[bot] commented #3110
  • May 12 17:41
    sonarcloud[bot] commented #3110
  • May 12 17:19
    sonarcloud[bot] commented #3111
  • May 12 17:19
    sonarcloud[bot] commented #3112
  • May 12 17:12
    shawkins synchronize #3110
  • May 12 16:55
    rohanKanojia opened #3112
  • May 12 16:36
    rohanKanojia commented #3036
  • May 12 16:21
    sonarcloud[bot] commented #3110
  • May 12 16:13
    rohanKanojia edited #3111
Brett Tofel
@bentito
I see io.fabric8.kubernetes.api.model.Context but not sure about how to match that up?
Rohan Kumar
@rohanKanojia
Hello
Could you please provide a link where this code is located? I'm not able to understand what it's doing.
Are you constructing a Context? Maybe you can use ContextBuilder?
Brett Tofel
@bentito
Yes, the Go is making a Context with a timeout and then using that time to exec the callback I think. I didn't find ContextBuilder before so let me read up on that to see if works for this.
thanks!
Rohan Kumar
@rohanKanojia
I wasn't able to find a withTimeout method but I didn't look closely
Sachin Mittal
@sjmittal
Hi
I want to delete all pods/services/deployments/etc under namespace (including the namespace)
is there a way to delete them and wait till all gets deleted in one command
the reason I need to wait is because a service of type loadbalancer creates a loadbalancer in AWS and I want to make sure that delete of this service also deletes the loadbalancer in AWS before I can proceed to next line of code
is this the right command
client.namespaces().withName(NAMESPACE).cascading(true).delete()
Sachin Mittal
@sjmittal
or is this the right command
client.namespaces().withName(NAMESPACE).withPropagationPolicy(DeletionPropagation.FOREGROUND).delete();
Marc Nuri
@manusa
Hi, Cascading is deprecated
Regarding the right propagation policy, please read the following documentation: https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/
With foreground, the owning resource will be visible through the API with a deletionTimestamp entry while the dependent resources are deleted.
With background, the owning resource is deleted immediately (not visible anymore), dependent resources are then deleted.
You need to see how these strategies fit in your requirements, and take into account you expectations when verifying or proceeding to your next steps.
Sachin Mittal
@sjmittal
ok then based on what you have mentioned none fits in with my case ..
is there any way to ensure all the services are deleted before deleting that namespace
Marc Nuri
@manusa
What I'm missing right now is why deleting your namespace doesn't delete all of the underlying resources.
Anyway, deleting any resource with FOREGROUND, verifying the resource has the deletionTimestamp and waiting until that resource disappears from the API (no longer queryable) should do the job. So basically you should waitUntil a condition in which that (parent) resource no longer exists.
Sachin Mittal
@sjmittal
it deletes the underlying resources .. though looks like the underlying AWS resources may not be deleted
like delete a service of type loadbalancer does not immediately delete a elb resource in AWS
so I was wondering to wait till that service is actually deleted and then execute next lines of code
Marc Nuri
@manusa
Well, if you want to double check, you can delete in foreground the LB (I guess the LoadBalancer doesn't have dependents) and then delete the namespace.
Sachin Mittal
@sjmittal
yes .. thats looks better
Marc Nuri
@manusa
OT, have you tried the ELB with websockets? The other day, another colleague was facing an issue with this.
Sachin Mittal
@sjmittal
not tried ELB with websockets .. but is this related to farbric8io client?
I am now deleting all the services of type LB before deleting the namespace
let me know this will work
NonNamespaceOperation<Service, ServiceList, ServiceResource<Service>> inNamespace = client.services().inNamespace(NAMESPACE);
inNamespace.list().getItems().stream()
    .filter(s -> "LoadBalancer".equals(s.getSpec().getType()))
    .forEach(s -> inNamespace.withName(s.getMetadata().getName()).withPropagationPolicy(DeletionPropagation.FOREGROUND).delete());
client.namespaces().withName(NAMESPACE).withPropagationPolicy(DeletionPropagation.FOREGROUND).delete();
Marc Nuri
@manusa

not tried ELB with websockets .. but is this related to farbric8io client?

No, not at all. Just curious in case you had any experience, it appears to be something that doesn't work well in AWS.

let me know this will work

I guess it should, yes.

Sachin Mittal
@sjmittal
I would be testing websockets with ELB later as we are building a gateway and we do have to support websockets
I will updated if I run into any problems
Marc Nuri
@manusa
:thumbsup: thx!
Fabian-K
@Fabian-K
Hi, the k8s api supports the resourceVersion parameter for get operations (https://kubernetes.io/docs/reference/using-api/api-concepts/#the-resourceversion-parameter). Is this also possible via the fabric8 client? e.g. getting the pod name in namespace not older than resource version 10? The following is not working
new DefaultKubernetesClient()
            .pods()
            .inNamespace("namespace").withName("name")
            .withResourceVersion("10")
            .get()
Rohan Kumar
@rohanKanojia
You can list with ListOptions
I think ListOptions has a resourceVersion parameter
I'm not sure if it'll work since I haven't tried it myself. Could you please try it out and provide feedback if it works or not?
1 reply
Akram Ben Aissi
@akram
Hi team, I am seeing that informers take 5 seconds to stop. This seems to be a fixed time unit. Can someone tell me if it is true? and point me to the relevant code?
My applications can have up to 200 informers in some configurations. And, in case of a configuration change, I may have to stop many of them, which is taking a lot of time.
11 replies
Chris Cooper
@coopstah13

hello, I'm trying to connect to a k8s instance that is using EC keys, but I'm getting NoClassDefFoundError here:

private static PrivateKey handleECKey(InputStream keyInputStream) throws IOException {
    // Let's wrap the code to a callable inner class to avoid NoClassDef when loading this class.
    try {
      return new Callable<PrivateKey>() {
        @Override
        public PrivateKey call() {
          try {
            if (Security.getProvider("BC") == null) {
              Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
            }
            PEMKeyPair keys = (PEMKeyPair) new PEMParser(new InputStreamReader(keyInputStream)).readObject();
            return new
              JcaPEMKeyConverter().
              getKeyPair(keys).
              getPrivate();
          } catch (IOException exception) {
            exception.printStackTrace();
          }
          return null;
        }
      }.call();
    } catch (NoClassDefFoundError e) {
      throw new KubernetesClientException("JcaPEMKeyConverter is provided by BouncyCastle, an optional dependency. To use support for EC Keys you must explicitly add this dependency to classpath.");
    }
  }

I cannot use bouncycastle, however, my JDK implementation does support EC keys as far as I'm aware (I see the code in the IDE). Is there a reason this cannot fall back to attempting to use the build in JCE provider should EC keys be available to it? Instead of just propagating up a KubernetesClientException.
https://stackoverflow.com/questions/22963581/reading-elliptic-curve-private-key-from-file-with-bouncycastle - this actually shows it should be possible without bouncycastle

basically i'm wondering what is the downside to calling return handleOtherKeys(keyInputStream, clientKeyAlgo); in the catch block instead of propagating the KubernetesClientException?
Rohan Kumar
@rohanKanojia
Is it possible for us to check whether EC key is supported in jdk before checking in bouncycastle?
8 replies
Akram Ben Aissi
@akram
image.png
21 replies
Florian Wiesner
@FWiesner
hi guys. It is possible to query a shared informer (factory) whether it is healthy?
paulgeiger-eng
@paulgeiger-eng

Following up on Florian's question above, I had been thinking that the Informer hasSynced method would return false after the watch had closed. However from my analysis of our code it looks like hasSynced is returning true even after the following exception:

2021-05-05 16:02:03.540+0000 | | ::: | OkHttp https://10.96 | | ERROR | io.fabric8.kubernetes.client.informers.cache.ReflectorWatcher | Watch closing
2021-05-05 16:07:08.656+0000 | | ::: | OkHttp WebSocket htt | | WARN | io.fabric8.kubernetes.client.dsl.internal.WatcherWebSocketListener | Exec Failure
java.net.SocketTimeoutException: sent ping but didn't receive pong within 30000ms (after 8 successful ping/pongs)
at okhttp3.internal.ws.RealWebSocket.writePingFrame(RealWebSocket.java:545)
at okhttp3.internal.ws.RealWebSocket$PingRunnable.run(RealWebSocket.java:529)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.lang.Thread.run(Thread.java:834)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:517)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:192)
2021-05-05 16:07:09.723+0000 | | ::: | OkHttp https://10.96 | | ERROR | io.fabric8.kubernetes.client.informers.cache.ReflectorWatcher | Watch closing

Rohan Kumar
@rohanKanojia
We recently added isRunning() is SharedInformer interface which can help you find out status of a particular sharedinformer: https://github.com/fabric8io/kubernetes-client/blob/master/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/informers/SharedInformer.java#L66
@paulgeiger-eng : It's quite strange. I remember we have a test to verify hasSynced turns false on watch issues: https://github.com/fabric8io/kubernetes-client/blob/master/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DefaultSharedIndexInformerTest.java#L332 . Could you please check if the test is validating your scenario or is it something different?
paulgeiger-eng
@paulgeiger-eng

Hi Rohan, thanks for looking into our issue. Would you say that isRunning or hasSynced is the best way to check the health of a SharedInformer?

I believe that the test you mentioned might not be validating our scenario. In our microservice we currently have code to call hasSynced before each access of the SharedInformer cache. The issue we observed is only in a live environment and we have not isolated it to a test case. What we believe is happening is that the SharedInformer initially syncs but later the cluster gets overloaded resulting in the above mentioned exception. I am confident that hasSynced must be returning true because we have observed a different scenario where the SharedInformer fails to sync and in that scenario our microservice fails. In the current scenario our microservice incorrectly continues to function with stale data from the SharedInformer cache.

paulgeiger-eng
@paulgeiger-eng

Rohan, I was looking at the test case you mentioned. I'm not familiar with the fabric8 code but what I infer from the test code is that the SharedInformer opens a connection to k8s and keeps the connection open while k8s sends watch events. The test case looks like it is sending an outdated watch event that the informer should detect, causing the hasSynced to return false.

In our scenario it seems likely that no outdated event is ever sent. It seems to be just an unexpected socket/connection error. The scenario occurs after creating a new resource in k8s of the same type as the informer. Very possibly the most recent event that the informer received was not outdated but the problem is that the informer does not pick up the new event from the resource creation.

Rohan Kumar
@rohanKanojia
@paulgeiger-eng : Would it be possible for you to open an issue so that we can investigate?
2 replies
Marc Nuri
@manusa
Hi everyone. To anyone who is affected right now, sorry for the delayed PR reviews and merge process.
We're currently working on a fix on the sundr.io dependency to mitigate one of the CRD-generator module failing tests.
This fix will however take a while, but we still need a sundr.io release to improve overall stability and performance.
Following is the list of expected next steps:
  1. Release of sundr.io 0.40.0
  2. Upgrade client dependency + disable failing test + open issue to re-enable
  3. Rebase current PRs and merge
  4. Release 5.4.
gp
@gp502

hello, we are trying to upgrade to 5.3.1 and our tests are failing because of a change in KubernetesCrudDispatcher.doCreate() - the resources always get a new uid in KubernetesCrudDispatcher.setDefaultMetadata() . We use the owner references uid for some operations and the changing uid on replace is causing problems.

Both KubernetesCrudDispatcher.handleCreate() and KubernetesCrudDispatcher.handleReplace() call KubernetesCrudDispatcher.doCreate(). So both created and replaced resources will get a new uid in setDefaultMetadata. This does not match the behavior of actual Kubernetes, where replaced resources maintain the same uid.

This is our groovy test to verify this behavior. The test passes when run against an actual Kubernetes server but fails with the fabric8 mock server at assert retrievedSecret.metadata.uid == secret.metadata.uid i.e., all assertions that compared retrieved secrets uid with the created secrets uid fail

def "test uid matches on update and get"() {
    given: "a namespace"
        String namespaceName =  UUID.randomUUID().toString()
        kubernetesClient.namespaces().createOrReplace(new NamespaceBuilder()
                .withNewMetadata()
                .withName(namespaceName)
                .endMetadata()
                .build())
    and: "a secret"
        def name = "secret-one"
        Secret secret = kubernetesClient.secrets()
                .inNamespace(namespaceName)
                .createOrReplace(new SecretBuilder()
                        .withMetadata(new ObjectMetaBuilder()
                                .withName(name)
                                .build()).build())
    expect: "secret has correct name and uid"
        assert secret.metadata.name == name
    when: "secret is retrieved"
        Secret retrievedSecret = kubernetesClient.secrets() .inNamespace(namespaceName).withName(name).get()
    then: "uid is same as when created"
        assert retrievedSecret.metadata.name == secret.metadata.name
        assert retrievedSecret.metadata.uid == secret.metadata.uid
    when: "secret is updated"
        Secret updatedSecret = kubernetesClient.secrets()
                .inNamespace(namespaceName)
                .createOrReplace(new SecretBuilder(secret)
                        .editOrNewMetadata()
                        .withName(name)
                        .endMetadata()
                        .addToStringData("Hello", "World")
                        .build())
    then: "uid is same as when created"
        assert updatedSecret.metadata.name == secret.metadata.name
        assert updatedSecret.metadata.uid == secret.metadata.uid
    when: "secret is retrieved again"
        retrievedSecret = kubernetesClient.secrets() .inNamespace(namespaceName).withName(name).get()
    then: "uid is same as when created"
        assert retrievedSecret.metadata.name == secret.metadata.name
        assert retrievedSecret.metadata.uid == secret.metadata.uid
}

Is there a way to keep the uid same on replace?

1 reply