Skip to content
This repository was archived by the owner on Jan 9, 2020. It is now read-only.

Conversation

@foxish
Copy link
Member

@foxish foxish commented Apr 25, 2017

Changes to the test framework to run a subset of the tests we have now against a GCE cluster
I'll convert the other tests to work against multi-node clusters in subsequent PRs.

cc @mccheah @ash211

@foxish
Copy link
Member Author

foxish commented Apr 25, 2017

I'd like to get this one reviewed before all else, because it makes the workflow a bit simpler without minikube.

val SingleNode, MultiNode = Value
}

object KubernetesClient {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or perhaps renamed to KubernetesIntegrationTestsFixtures. Primarily it would be good to:

  • Contrast this with KubernetesTestComponents if they are different, and
  • Rename from KubernetesClient since this is also used by the Fabric8 client - maybe KubernetesTestClient?

Some Scaladoc on this class and its purpose could be a good idea, e.g. "Controls the Kubernetes cluster that integration tests are run against."

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

KubernetesTestClient makes sense. Will do & add doc.

@foxish
Copy link
Member Author

foxish commented Apr 25, 2017

rerun unit tests please

val SingleNode, MultiNode = Value
}

object KubernetesClient {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this necessarily has to be an object as a static singleton. Similarly for Minikube - we did start off with that being an object but it would probably be cleaner to use classes and dynamic instances if only to move away from global state.

If KubernetesV1Suite and KubernetesV2Suite need to share instances of these, they can be passed into the constructors from the parent KubernetesSuite#nestedSuites.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing it around everywhere seemed less than ideal. Since this will be shared across all testsuites, I felt this was easier to understand. Is it an anti-pattern here?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Minikube considering it's managing global state anyways (the execution of the Minikube binary) that one perhaps makes sense to stay as an object. Otherwise, I think making the sharing explicit in the method contract would make the test dependencies easier to trace around. For example, right now KubernetesV2Suite can be executed on its own e.g. in IntelliJ but when it does it won't have the lifecycle management that KubernetesSuite is setting up.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.. I see. That's a good point. It seems like if I put in those args, we'll lose the ability to run each of those tests separately from intellij. Any way to keep both? What do you think of having each testsuite (v1 and v2) initialize its own client? Since eventually we're only going to have one, it would be temporary.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was the idea we had before - KubernetesTestComponents is responsible for the Kubernetes client, but the parent suite KubernetesSuite is responsible for the global state, that is, the Minikube cluster. Global state should still be kept in the Minikube object - the user can run each individual test by starting Minikube and building the docker images themselves manually, for example. We essentially want to preserve these semantics.

}

private def createDefaultClient(): Unit = {
System.getProperty("spark.docker.test.master") match {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Option(System.getProperty(...)).map(...).getOrElse(...)

import org.apache.spark.internal.Logging
import org.apache.spark.util.Utils

object Util extends Logging {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use specific names for different kinds of utilities. E.g. UnixProcessUtils.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Javadoc this method also.


object KubernetesClient {
var defaultClient: DefaultKubernetesClient = _
var testBackend: TestBackend.Value = _
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could perhaps be thought of in a polymorphic approach. What if we had IntegrationTestBackend as the parent class with methods like initialize (Minikube builds docker images), getKubernetesClient and cleanUp, then, a factory class switches on the setting of the system property to choose the implementation.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of getKubernetesClient being an abstract method on such an abstract parent class, maybe getKubernetesClient is a final method which invokes the polymorphic getKubernetesClientConfig which varies depending on the backend.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea. I'm tempted to punt it for later though, since right now there's still quite a bit of Minikube being used directly in a lot of places. Ideally, once we move all of it out and clearly define the boundaries of backends, we can abstract out all the cluster specific operations into IntegrationTestBackend abstract parent, or trait. WDYT?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that the polymorphic test architecture could belong in the scope of this PR - if we're moving towards multiple back ends, it would be nice if we captured the overall architecture on this pass. If we are concerned that such a change would create too large of a diff, can we create a separate PR that merges into this one that implements the polymorphic architecture, merge said separate PR first into this branch, and then merge this PR?

This is primarily to ease review. Much of what could be commented on for this PR could be contingent on whether or not a polymorphic approach is used.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dependent PR works. I'll send one out later today then.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened #248

@tnachen
Copy link

tnachen commented Apr 26, 2017

+1!

* Restructured the test backends

* Address comments

* var -> val
servicePortName: String,
servicePath: String = ""): T = synchronized {
val kubernetesMaster = s"${defaultClient.getMasterUrl}"
val httpClient = getHttpClient(kubernetesClient.asInstanceOf[BaseClient])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we use this anywhere?

Copy link

@mccheah mccheah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed a tiny detail from the upstream PR. There also appears to be an unused http client field. After those changes I'm ok to merge this.

private[spark] object IntegrationTestBackendFactory {
def getTestBackend(): IntegrationTestBackend = {
Option(System.getProperty("spark.kubernetes.test.master")).map {
master =>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit - Can use .map(new GCETestBackend(_)) where the underscore passes in the master.

@foxish
Copy link
Member Author

foxish commented May 1, 2017

Looks like the integration test is wedged. @kimoonkim @varunkatta could you please restart it?

@foxish
Copy link
Member Author

foxish commented May 1, 2017

@mccheah tests passed. ok to merge?

HttpClientUtil.createClient[T](Set(url), 5, sslContext.getSocketFactory, trustManager)
}

def getHttpClient(client: BaseClient): OkHttpClient = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we use this anywhere?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I missed that one. Sorry!
We'll likely need that http client later, because I think we shouldn't rely on minikube credentials to hit the api-server proxy endpoint, but I'll get rid of it now.

@mccheah mccheah merged commit 6b489c2 into branch-2.1-kubernetes May 2, 2017
foxish added a commit that referenced this pull request Jul 24, 2017
* Part 1: making test code cluster-agnostic

* Final checked

* Move all test code into KubernetesTestComponents

* Addressed comments

* Fixed doc

* Restructure the test backends (#248)

* Restructured the test backends

* Address comments

* var -> val

* Comments

* removed deadcode
@foxish foxish deleted the multi-k8s-tests branch July 25, 2017 00:48
ifilonenko pushed a commit to ifilonenko/spark that referenced this pull request Feb 26, 2019
puneetloya pushed a commit to puneetloya/spark that referenced this pull request Mar 11, 2019
* Part 1: making test code cluster-agnostic

* Final checked

* Move all test code into KubernetesTestComponents

* Addressed comments

* Fixed doc

* Restructure the test backends (apache-spark-on-k8s#248)

* Restructured the test backends

* Address comments

* var -> val

* Comments

* removed deadcode
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants