fabric8io / fabric8

fabric8 is an open source microservices platform based on Docker, Kubernetes and Jenkins
http://fabric8.io/
1.76k stars 504 forks source link

fabric8:json needs access to OpenShift ? #4962

Open rhuss opened 9 years ago

rhuss commented 9 years ago

While doing an s2i test, for a build which has fabric8:json attached to its package phase, I see the following error in the log:

Downloaded: http://repo.maven.apache.org/maven2/org/eclipse/jgit/org.eclipse.jgit/4.1.0.201509280440-r/org.eclipse.jgit-4.1.0.201509280440-r.jar (2113 KB at 477.6 KB/sec)
I1014 09:23:45.160599 02700 sti.go:406] [INFO] Configured with file: /tmp/src/target/classes/kubernetes.json
I1014 09:23:45.247936 02700 sti.go:406] 2015-10-14 07:23:45 INFO  Version:17 - HV000001: Hibernate Validator 5.2.2.Final
I1014 09:23:45.484530 02700 sti.go:406] [INFO] No environment schemas found for file: io/fabric8/environment/schema.json
I1014 09:23:45.485614 02700 sti.go:406] [INFO] Generated env mappings: {}
I1014 09:23:45.540989 02700 sti.go:406] [INFO] Generated port mappings: {jolokia=ContainerPort(containerPort=8778, hostIP=null, hostPort=null, name=jolokia, protocol=null, additionalProperties={})}
I1014 09:23:46.302590 02700 sti.go:406] [INFO] Removed 'version' label from service selector for service `camel-cdi`
I1014 09:23:46.328639 02700 sti.go:406] Generated ports: []
I1014 09:23:46.390566 02700 sti.go:406] [INFO] Icon URL: https://cdn.rawgit.com/fabric8io/fabric8/master/fabric8-maven-plugin/src/main/resources/icons/camel.svg
I1014 09:23:46.753580 02700 sti.go:406] [WARNING] Could not find .git folder based on the current basedir of /tmp/src
I1014 09:23:46.753599 02700 sti.go:406] [WARNING] Could not find .git folder based on the current basedir of /tmp/src
I1014 09:23:46.753603 02700 sti.go:406] [WARNING] Cannot default GIT_COMMIT as no git repository could be found
I1014 09:23:46.753606 02700 sti.go:406] [WARNING] Cannot auto-default GIT_URL as there is no environment variable `JENKINS_GOGS_USER` defined so we can't guess the Gogs build URL
I1014 09:23:46.753609 02700 sti.go:406] [WARNING] Cannot auto-default BUILD_URL as there is no environment variable `JENKINS_GOGS_USER` defined so we can't guess the Jenkins build URL
I1014 09:23:47.935521 02700 sti.go:406] [WARNING] Cannot find jenkins service URL: io.fabric8.kubernetes.client.KubernetesClientException: An error has occurred.
I1014 09:23:47.935545 02700 sti.go:406] io.fabric8.kubernetes.client.KubernetesClientException: An error has occurred.
I1014 09:23:47.935550 02700 sti.go:406]     at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:53)
I1014 09:23:47.935555 02700 sti.go:406]     at io.fabric8.kubernetes.client.dsl.internal.BaseOperation.get(BaseOperation.java:121)
I1014 09:23:47.935559 02700 sti.go:406]     at io.fabric8.kubernetes.api.KubernetesHelper.getServiceURLInCurrentNamespace(KubernetesHelper.java:1303)
I1014 09:23:47.935563 02700 sti.go:406]     at io.fabric8.maven.AbstractFabric8Mojo.tryDefaultAnnotationEnvVar(AbstractFabric8Mojo.java:417)
I1014 09:23:47.935566 02700 sti.go:406]     at io.fabric8.maven.AbstractFabric8Mojo.addEnvironmentAnnotations(AbstractFabric8Mojo.java:363)
I1014 09:23:47.935570 02700 sti.go:406]     at io.fabric8.maven.AbstractFabric8Mojo.addEnvironmentAnnotations(AbstractFabric8Mojo.java:336)
I1014 09:23:47.935649 02700 sti.go:406]     at io.fabric8.maven.AbstractFabric8Mojo.addEnvironmentAnnotations(AbstractFabric8Mojo.java:313)
I1014 09:23:47.935663 02700 sti.go:406]     at io.fabric8.maven.JsonMojo.execute(JsonMojo.java:511)
I1014 09:23:47.935668 02700 sti.go:406]     at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
I1014 09:23:47.935672 02700 sti.go:406]     at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
I1014 09:23:47.935676 02700 sti.go:406]     at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
I1014 09:23:47.935680 02700 sti.go:406]     at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
I1014 09:23:47.935683 02700 sti.go:406]     at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
I1014 09:23:47.935687 02700 sti.go:406]     at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
I1014 09:23:47.935879 02700 sti.go:406]     at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
I1014 09:23:47.935889 02700 sti.go:406]     at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
I1014 09:23:47.935894 02700 sti.go:406]     at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
I1014 09:23:47.935898 02700 sti.go:406]     at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
I1014 09:23:47.935902 02700 sti.go:406]     at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
I1014 09:23:47.935906 02700 sti.go:406]     at org.apache.maven.cli.MavenCli.execute(MavenCli.java:862)
I1014 09:23:47.935910 02700 sti.go:406]     at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:286)
I1014 09:23:47.935914 02700 sti.go:406]     at org.apache.maven.cli.MavenCli.main(MavenCli.java:197)
I1014 09:23:47.936034 02700 sti.go:406]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
I1014 09:23:47.936048 02700 sti.go:406]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
I1014 09:23:47.936053 02700 sti.go:406]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
I1014 09:23:47.936057 02700 sti.go:406]     at java.lang.reflect.Method.invoke(Method.java:497)
I1014 09:23:47.936061 02700 sti.go:406]     at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
I1014 09:23:47.936065 02700 sti.go:406]     at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
I1014 09:23:47.936069 02700 sti.go:406]     at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
I1014 09:23:47.936072 02700 sti.go:406]     at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
I1014 09:23:47.936076 02700 sti.go:406] Caused by: java.util.concurrent.ExecutionException: java.net.UnknownHostException: kubernetes.default.svc: unknown error
I1014 09:23:47.936187 02700 sti.go:406]     at com.ning.http.client.providers.netty.future.NettyResponseFuture.abort(NettyResponseFuture.java:231)
I1014 09:23:47.936200 02700 sti.go:406]     at com.ning.http.client.providers.netty.request.NettyRequestSender.abort(NettyRequestSender.java:420)
I1014 09:23:47.936204 02700 sti.go:406]     at com.ning.http.client.providers.netty.request.NettyRequestSender.sendRequestWithNewChannel(NettyRequestSender.java:288)
I1014 09:23:47.936210 02700 sti.go:406]     at com.ning.http.client.providers.netty.request.NettyRequestSender.sendRequestWithCertainForceConnect(NettyRequestSender.java:140)
I1014 09:23:47.936216 02700 sti.go:406]     at com.ning.http.client.providers.netty.request.NettyRequestSender.sendRequest(NettyRequestSender.java:115)
I1014 09:23:47.936222 02700 sti.go:406]     at com.ning.http.client.providers.netty.NettyAsyncHttpProvider.execute(NettyAsyncHttpProvider.java:87)
I1014 09:23:47.937532 02700 sti.go:406]     at com.ning.http.client.AsyncHttpClient.executeRequest(AsyncHttpClient.java:506)
I1014 09:23:47.937543 02700 sti.go:406]     at com.ning.http.client.AsyncHttpClient$BoundRequestBuilder.execute(AsyncHttpClient.java:229)
I1014 09:23:47.937547 02700 sti.go:406]     at io.fabric8.kubernetes.client.dsl.internal.BaseOperation.handleResponse(BaseOperation.java:565)
I1014 09:23:47.937551 02700 sti.go:406]     at io.fabric8.kubernetes.client.dsl.internal.BaseOperation.handleGet(BaseOperation.java:596)
I1014 09:23:47.937554 02700 sti.go:406]     at io.fabric8.kubernetes.client.dsl.internal.BaseOperation.get(BaseOperation.java:114)
I1014 09:23:47.937558 02700 sti.go:406]     ... 28 more
I1014 09:23:47.937561 02700 sti.go:406] Caused by: java.net.UnknownHostException: kubernetes.default.svc: unknown error
I1014 09:23:47.937567 02700 sti.go:406]     at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
I1014 09:23:47.937571 02700 sti.go:406]     at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:928)
I1014 09:23:47.938710 02700 sti.go:406]     at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1323)
I1014 09:23:47.938721 02700 sti.go:406]     at java.net.InetAddress.getAllByName0(InetAddress.java:1276)
I1014 09:23:47.938725 02700 sti.go:406]     at java.net.InetAddress.getAllByName(InetAddress.java:1192)
I1014 09:23:47.938728 02700 sti.go:406]     at java.net.InetAddress.getAllByName(InetAddress.java:1126)
I1014 09:23:47.938732 02700 sti.go:406]     at java.net.InetAddress.getByName(InetAddress.java:1076)
I1014 09:23:47.938735 02700 sti.go:406]     at com.ning.http.client.NameResolver$JdkNameResolver.resolve(NameResolver.java:28)
I1014 09:23:47.938739 02700 sti.go:406]     at com.ning.http.client.providers.netty.request.NettyRequestSender.remoteAddress(NettyRequestSender.java:356)
I1014 09:23:47.938742 02700 sti.go:406]     at com.ning.http.client.providers.netty.request.NettyRequestSender.connect(NettyRequestSender.java:367)
I1014 09:23:47.938746 02700 sti.go:406]     at com.ning.http.client.providers.netty.request.NettyRequestSender.sendRequestWithNewChannel(NettyRequestSender.java:281)
I1014 09:23:47.939929 02700 sti.go:406]     ... 36 more
I1014 09:23:47.939941 02700 sti.go:406] [INFO] Added environment annotations:
I1014 09:23:47.939944 02700 sti.go:406] [INFO]     ReplicationController camel-cdi replicas: 1, image: docker.io/fabric8/camel-cdi:1.0-SNAPSHOT
I1014 09:23:47.939948 02700 sti.go:406] [INFO] Template is now:
I1014 09:23:47.939951 02700 sti.go:406] [INFO]     ReplicationController camel-cdi replicas: 1, image: docker.io/fabric8/camel-cdi:1.0-SNAPSHOT
I1014 09:23:47.965360 02700 sti.go:406] [INFO]
I1014 09:23:47.965380 02700 sti.go:406] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ camel-cdi ---
I1014 09:23:47.965384 02700 sti.go:406] Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/maven-plugin-api/2.0.6/maven-plugin-api-2.0.6.pom
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/maven-plugin-api/2.0.6/maven-plugin-api-2.0.6.pom (0 B at 0.0 KB/sec)
I1014 09:23:48.011380 02700 sti.go:406] Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/maven/2.0.6/maven-2.0.6.pom
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/maven/2.0.6/maven-2.0.6.pom (0 B at 0.0 KB/sec)

This is of course correct, since the environment is not set for direct OpenShift API access. I wonder whether fabric8:json is supposed to do this (accessing the OS API) or isn't it all about generating a JSON file ?

Btw, the warning here are still very disturbing, too. There should be another way to connect DevOps to this plugin so that the plugin stays agnostic to DevOps. Otherwise coupling will kill us sooner or later.

jstrachan commented 9 years ago

BTW I've updated the code to only warn about not being able to find Jenkins / Gogs and the like if JENKINS_HOME is defined by default (you can override the environment variable to detect it).

Its a tricky one really; ideally we'd annotate an RC with the git commit / URL / build that created it at the "fabric8:json" time.

Maybe we just need to define an env var or something so that we know its inside an S2I image so we can annotate the json with the S2I image URL instead of jenkins?

BTW why is there no .git repository found I wonder? At a bare minimum we should annotate the git commit ID on all builds?

rhuss commented 9 years ago

But then maybe the default binding to the package phase for 'fabric8:json' is not so appropriate becaus of this 'calling out' ? s2i builds don't need this. another use case is building the docker image and run it locally.

s2i does some heavy copying on source files before starting the build, wiping out the local git repo. This will probably will break other builds which e.g. pick up some version numbers from a local git repo, too.

If I understand right, you need the OpenShift API in order to query some meta data (sorry, still not in the details :). But there will be many situation where this is not guaranteed. For 'fabric8:apply' ok, there is supposed to be an API server alive. But for 'fabric8:json' (which creates a JSON file) it should be possible also without. Maybe we can make it switchable via configuration whether the DevOps metadata should be attached or not ?

jstrachan commented 8 years ago

We could certainly have environment variables / CLI arguments to opt out of generating the metadata.

However we should always strive to add as much metadata to the JSON as we can (e.g. git commit/URL metadata for sure; for a S2I build we should link to the build number/log too).

BTW when running inside Kubernetes, we'll have environment variables to be able to find things like gogs / jenkins; so we won't need to use the Kubernetes REST API directly; though for generating external links (e.g. public links to git / jenkins) thats kinda hard without using the REST APIs - maybe we'd need to pass those into the S2I builder as environment variables?

rhuss commented 8 years ago

I agree in attaching as many meta data as possible and available. My concern is about coupling: If you have a general purpose plugin like the fabric8-maven-plugin which refers to a specific feature which might not be available (like this JENKINS_GOGS_USER), it couples the plugin this other app/feature which makes maintenance harder (when you change devops you to think to update fabric8-maven-plugin, too).

If it would be the other way round, that the fabric8-maven-plugin extract information from its direct context (i.e. pom.xml) and someon picks that up it would stay independent (i.e. can run for sure even when the devops changes).

For me it also feels a bit wrong to put current runtime information obtained from the OpenShift API into a build config which can end up in a Maven repo and reused somewhere else where this runtime is different. It's my feeling that this information should be injected during runtime when or after the app is deployed.

jstrachan commented 8 years ago

How at runtime of a docker container can you know the git commit, the jenkins build URL and the URL to browse the source code - without putting that metadata somewhere?

Its common practice in CI/CD to put git commit ID, branch, git hosting URL, issues fixed, CI build URLs and so forth inside jar manifests to aid traceability. I'm not sure why OpenShift templates are not any different? They are a natural place to put metadata about source code, commits, builds and so forth to aid traceability from runtimes to the various source / issue tracker / build systems together. I'm all for doing the same with docker images and jar manifests too BTW.

The generic, non release specific stuff tends to be in the pom.xml anyway (the top level URL for git, website, mailing list etc). It just doesn't host release specific stuff.

There's a maven plugin coupling if we did the same thing for jar manifest + openshift template + docker image labels; as each of those plugins needs to know where to pull this metadata. Ideally we'd just define them all as system properties or env vars or a canonical build file or something and generate it by a separate plugin (is that maybe what you were getting at?); so that we don't have to spread this logic between lots of different maven plugins (which might make it easier to enable/disable via profiles or whatever the CI/CD metadata generation).

What I'd like is for each jar (https://github.com/fabric8io/fabric8/issues/5058), docker image (https://github.com/fabric8io/fabric8/issues/4575) and kubernetes template to have all of these annotations in them: http://fabric8.io/guide/annotations.html#continous-delivery-annotations

I'd like to add some more too really; e.g. an annotation to point at a list of all issues resolved in this release (versus the previous one) - https://github.com/fabric8io/fabric8/issues/4888 - along with annotations to point at the browseable javadoc and maven site: https://github.com/fabric8io/fabric8/issues/4924

iocanel commented 8 years ago

We already use the concept of @KubernetesModelProcessor in order to define decorator for the generated JSON and cover cases where maven plugin is not enough.

This allows decorating the JSON, without polluting/coupling to the plugin.

We could use a similar concept here.

We can create a decorator which would be responsible for enriching any JSON with CI/CD related information. Then we should find a way to kick the decorator if it is present in the classpath or something like this.

It could possibly work with java.util.ServiceLoader or by scanning for annotating classes or whatever we choose. I think this way we have a win-win.

davsclaus commented 8 years ago

See also #5090