This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-07-20
Channels
- # announcements (1)
- # babashka (32)
- # beginners (100)
- # cider (43)
- # clj-kondo (4)
- # cljdoc (3)
- # cljs-dev (5)
- # cljsjs (2)
- # cljsrn (22)
- # clojure (170)
- # clojure-australia (27)
- # clojure-europe (25)
- # clojure-nl (3)
- # clojure-uk (76)
- # clojurescript (127)
- # conjure (14)
- # core-matrix (1)
- # cursive (9)
- # datomic (6)
- # defnpodcast (1)
- # emacs (32)
- # events (1)
- # expound (77)
- # fulcro (30)
- # graalvm (21)
- # graalvm-mobile (30)
- # helix (4)
- # honeysql (1)
- # hyperfiddle (1)
- # jackdaw (8)
- # jobs (6)
- # kaocha (1)
- # leiningen (4)
- # lsp (16)
- # malli (46)
- # meander (4)
- # off-topic (19)
- # pathom (10)
- # podcasts (1)
- # portal (2)
- # re-frame (7)
- # reagent (2)
- # releases (1)
- # remote-jobs (11)
- # rewrite-clj (8)
- # shadow-cljs (9)
- # tools-deps (243)
- # vim (1)
Morning βοΈ
Hi guys;
I have a (slightly off topic) Docker / TeamCity Agent / Gradle problem that I am running out of ideas on
I am trying to run http://testcontainers.org mongo db from within an integration test
but it is blowing up on init()
, essentially because it is trying to check System.getenv("PATH")
but it is getting a null response
This is only happening when it runs on the Dockerized TeamCity agent
I can echo $PATH
on a bash process within the agent container, and I get a sensible result
There's a load of sequentially forked java processes:
1. jetbrains.buildServer.agent.Launcher
2. jetbrains.buildServer.agent.AgentMain
3. org.gradle.wrapper.GradleWrapperMain
4. org.gradle.launcher.daemon.bootstrap.GradleDaemon
5. http://worker.org.gradele.process.internal.worker.GradleWorkerMain
I think its that last one that is actually failing
Any suggestions?
I'm expecting the system environment variables to get passed between forked processes
but perhaps I dont understand anything...
well I don't actually know how they got spawned
I just know that ps
reports a parentage
Which container are you running the echo in? The agent container, or the mongo container?
Oh, if this is the JVM spawning other JVMs, then I bet it doesn't convey the environment.
I am running the echo in the agent container
I'm naively ignoring the mongo container and hoping that http://test-container.org knows what it is about
but I think I get the NPE before testcontainers does any real work
I assume you've checked that you can run Docker-in-Docker on the build agent, if it's already a Docker container?
Just checked, java.lang.Process does keep the environment unless you explicitly change it.
> I assume you've checked that you can run Docker-in-Docker on the build agent, if it's already a Docker container? I am expecting this to be a problem but I was tacking the NullPointerException first unless they are somehow the same problem..?
but I think the Gradle Daemon is just a plain old jvm isn't it
When we were using gitlab (in my previous job) we always had this on our build steps
yes I think that IS set in my case - but it stll runs the org.gradle.launcher.daemon.bootstrap.GradleDaemon
class
it run TeamCity agent on java8 and flips to java13 for gradle dunno if that is important...
I haven't used Gradle in ages, but I seem to recall that you need to explicitly make environment variables available to it
This answer also suggests it: https://stackoverflow.com/questions/27530263/unable-to-build-gstreamer-tutorials-using-android-studio
thanks for suggestions
I can manually trigger
gradlew -Dorg.gradle.daemon=false --info integration-test:test
from bash shell on the docker instance
and my test class successfully printout all the System.getenv()
values I would have expected...
so it must be somthing about how TeamCity Agent spawns the gradlewrapper that is depriving it of environment vars
I guess
Update: I have just discovered the delightfully named
fun hackilySetStuffInTheEnv(passwords: Map<String,String>) {
whos running seems strongly correlated with the results of
System.getenv("PATH")
going tits-upthanks for all your suggestions; in this case I suspect that Docker - TeamCityAgent - Gradle - TestContainer are all behaving themselves and its my team's dodgy code that is the issue
no it was using some horrible non public api I think
will report back on Monday
oh I see he copy-and-pasted from https://stackoverflow.com/a/7201825/89109
that code fragment does a hard-to-understand thing in the catch block; I suspect that this does not work, (probaly has never worked)
protected static void setEnv(Map<String, String> newenv) throws Exception {
try {
...
} catch (NoSuchFieldException e) {
Class[] classes = Collections.class.getDeclaredClasses();
Map<String, String> env = System.getenv();
for(Class cl : classes) {
if("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
Object obj = field.get(env);
Map<String, String> map = (Map<String, String>) obj;
map.clear();
map.putAll(newenv);
}
this is exactly why I am so dubious about github copilot
I believe the phrase is > flood the zone with shit
It's simply abusing reflection and the JVM internals in a perfectly clear and horrifying way
but how the hell is it set setting environment variables by abusing unmodifiable map?
oh now I see
well, makes me glad I'm charging by the day
It annoys me because it is so completely unnecessary
It can be simplified by using plain old System.setProperty()
https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/lang/System.html#setProperty(java.lang.String,java.lang.String)
and then the password accessors just have to read from eith Environment OR java property
and thats a pattern you always want, imho
because it gives you so much more flexibility
(and works properly)
CoPilot is worse than StackOverflow - at least with StackOverflow you get context about what probably is being solved, comments on different approaches, pros and cons etc, and people will explain why a bad solution is a bad. With CoPilot you donβt get that
but java doesn't know where it is running
java cannot assume where it will eventually be running
might not be a posix env
The real pro move is to assume you're running on Linux like Go does and silently fail to do things properly if you're not
so thats where I've been going wrong all this time
possessing a conscience can be so disabling
back to
rotected static void setEnv(Map<String, String> newenv) throws Exception {
try {
...
} catch (NoSuchFieldException e) {
Class[] classes = Collections.class.getDeclaredClasses();
Map<String, String> env = System.getenv();
for(Class cl : classes) {
if("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
Object obj = field.get(env);
Map<String, String> map = (Map<String, String>) obj;
** map.clear(); **
map.putAll(newenv);
}
I reckon if get rid of that map.clear()
my immediate problem might go awayI dont understand what the clear is trying to achieve, other than destroying everthing
I presume the intent is to overwrite whatever's there with the new environment map. It would be better to merge the two maps
yeah if we just do the putAll
on top of what was there before
I'll try it as a quick fix
whilst I contemplate replacing with JVM Properties
when you are copy-and-pasting StackOverflow code, do you not always credit it with the relevant SO url in a comment? surely that is common courtesy to Those Who Come After You
Update: I have just discovered the delightfully named
fun hackilySetStuffInTheEnv(passwords: Map<String,String>) {
whos running seems strongly correlated with the results of
System.getenv("PATH")
going tits-up