spring-cloud / spring-cloud/spring-cloud-netflix

Eureka FreeMarker template error in AMI's column when running in AWS Fargate with private IP

Open
#3,703 8 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Java
Stars
5k
Forks
2.5k
Avg merge
1d 2h
Merged PRs (30d)
10

Description

I've successfully connected one of our microservices to Eureka using Fargate. Eureka is currently on an actual EC2 instance and microservices will be running from Fargate (hopefully Eureka too if I manage to get it to work). I have already got this running properly (or it seems as microservices connect to Eureka), with that said, I am getting a FreeMarker template error on the Eureka status page under the AMIs columns in "Instances currently registered with Eureka".

What I have done to achieve this Fargate to EC2 Eureka connection with private IP is the following. This dockerfile loads an entrypoint file which runs a shell script.

Dockerfile:

#############
### build ###
#############

# base image
FROM maven:3.6.2-ibmjava-8-alpine as build

# set working directory
WORKDIR /app


# install and cache app dependencies
COPY . /app
RUN mvn clean package


############
### prod ###
############

# base image
FROM openjdk:8-alpine

RUN apk add jq

# set working directory
WORKDIR /app

# copy entrypoint from the 'build environment'
COPY --from=build /app/entrypoint.sh /app/entrypoint.sh

# copy artifact build from the 'build environment'
COPY --from=build /app/target/user-service-0.0.1-SNAPSHOT.jar /app/user-service-0.0.1-SNAPSHOT.jar

# expose port 8081
EXPOSE 8081

# run entrypoint
ENTRYPOINT ["/bin/sh", "./entrypoint.sh"]

This entrypoint shell script saves the private IP from the Fargate metadata endpoint into the shell session.
entrypoint.sh:

#!/bin/sh
export FARGATE_IP=$(wget -q -O - http://169.254.170.2/v2/metadata | jq -r .Containers[0].Networks[0].IPv4Addresses[0])
echo $FARGATE_IP
java -jar user-service-0.0.1-SNAPSHOT.jar

The application property file loads the Fargate private IP so the microservice connects successfully.
application-aws.properties

eureka.client.region=us-east-1
eureka.client.use-dns-for-fetching-service-urls=true
eureka.client.eureka-server-u-r-l-context=eureka
eureka.client.eureka-server-d-n-s-name=eureka.domain.com
eureka.client.eureka-server-port=8761
eureka.instance.prefer-ip-address=true
eureka.instance.ip-address=${FARGATE_IP}
eureka.instance.non-secure-port=8081

This is the error I receive on the Eureka page under the AMIs column even though the services seem to work. Any ideas?

FreeMarker template error (DEBUG mode; use RETHROW in production!): 
The following has evaluated to null or missing: ==> amiCount.key [in template "eureka/status.ftl" at line 35, column 26] 
---- Tip: It's the step after the last dot that caused this error, not those before it.
---- Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- 
---- FTL stack trace ("~" means nesting-related): - Failed at: ${amiCount.key} [in template "eureka/status.ftl" at line 35, column 24] ---- Java stack trace (for programmers): 
---- freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...]
 at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134)
 at freemarker.core.EvalUtil.coerceModelToTextualCommon(EvalUtil.java:467)
 at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:389)
 at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:358)
 at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:100)
 at freemarker.core.DollarVariable.accept(DollarVariable.java:63)
 at freemarker.core.Environment.visit(Environment.java:366)
 at freemarker.core.IteratorBlock$IterationContext.executedNestedContentForCollOrSeqListing(IteratorBlock.java:317)
 at freemarker.core.IteratorBlock$IterationContext.executeNestedContent(IteratorBlock.java:271)
 at freemarker.core.IteratorBlock$IterationContext.accept(IteratorBlock.java:242)
 at freemarker.core.Environment.visitIteratorBlock(Environment.java:642)
 at freemarker.core.IteratorBlock.acceptWithResult(IteratorBlock.java:107)
 at freemarker.core.IteratorBlock.accept(IteratorBlock.java:93)
 at freemarker.core.Environment.visit(Environment.java:366)
 at freemarker.core.IteratorBlock$IterationContext.executedNestedContentForCollOrSeqListing(IteratorBlock.java:317)
 at freemarker.core.IteratorBlock$IterationContext.executeNestedContent(IteratorBlock.java:271)
 at freemarker.core.IteratorBlock$IterationContext.accept(IteratorBlock.java:242)
 at freemarker.core.Environment.visitIteratorBlock(Environment.java:642)
 at freemarker.core.IteratorBlock.acceptWithResult(IteratorBlock.java:107)
 at freemarker.core.IteratorBlock.accept(IteratorBlock.java:93)
 at freemarker.core.Environment.visit(Environment.java:330)
 at freemarker.core.Environment.visit(Environment.java:336)
 at freemarker.core.Environment.visit(Environment.java:336)
 at freemarker.core.Environment.process(Environment.java:309)
 at freemarker.template.Template.process(Template.java:384)
 at org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:389)
 at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:302)
 at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:253)
 at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:178)
 at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:316)
 at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1371)
 at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1117)
 at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1056)
 at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
 at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
 at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
 at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114)
 at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
 at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
 at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
 at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
 at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853)
 at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
 at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
 at java.lang.Thread.run(Thread.java:748)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with eureka/status.ftl at line 35, then trace the AMI data supplied for instances registered with private Fargate IPs. Reproduce the status page with the reported registration details and verify that the AMIs column renders without a FreeMarker missing-value error.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, docker, java, spring
Domain
backend, cloud
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.