1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache license, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the license for the specific language governing permissions and 15 * limitations under the license. 16 */ 17 package org.apache.logging.log4j.kubernetes; 18 19 import java.io.File; 20 import java.io.IOException; 21 import java.nio.file.Files; 22 import java.nio.file.Path; 23 import java.util.Objects; 24 25 import org.apache.logging.log4j.Logger; 26 import org.apache.logging.log4j.status.StatusLogger; 27 28 /** 29 * Locate the current docker container. 30 */ 31 public class ContainerUtil { 32 private static final Logger LOGGER = StatusLogger.getLogger(); 33 private static final int MAXLENGTH = 65; 34 35 /** 36 * Returns the container id when running in a Docker container. 37 * 38 * This inspects /proc/self/cgroup looking for a Kubernetes Control Group. Once it finds one it attempts 39 * to isolate just the docker container id. There doesn't appear to be a standard way to do this, but 40 * it seems to be the only way to determine what the current container is in a multi-container pod. It would have 41 * been much nicer if Kubernetes would just put the container id in a standard environment variable. 42 * 43 * @see <a href="http://stackoverflow.com/a/25729598/12916">Stackoverflow</a> for a discussion on retrieving the containerId. 44 * @see <a href="https://github.com/jenkinsci/docker-workflow-plugin/blob/master/src/main/java/org/jenkinsci/plugins/docker/workflow/client/ControlGroup.java>ControlGroup</a> 45 * for the original version of this. Not much is actually left but it provided good inspiration. 46 */ 47 public static String getContainerId() { 48 try { 49 File file = new File("/proc/self/cgroup"); 50 if (file.exists()) { 51 Path path = file.toPath(); 52 String id = Files.lines(path).map(ContainerUtil::getContainerId).filter(Objects::nonNull) 53 .findFirst().orElse(null); 54 LOGGER.debug("Found container id {}", id); 55 return id; 56 } 57 LOGGER.warn("Unable to access container information"); 58 } catch (IOException ioe) { 59 LOGGER.warn("Error obtaining container id: {}", ioe.getMessage()); 60 } 61 return null; 62 } 63 64 private static String getContainerId(String line) { 65 // Every control group in Kubernetes will use 66 if (line.contains("/kubepods")) { 67 // Strip off everything up to the last slash. 68 int i = line.lastIndexOf('/'); 69 if (i < 0) { 70 return null; 71 } 72 // If the remainder has a period then take everything up to it. 73 line = line.substring(i + 1); 74 i = line.lastIndexOf('.'); 75 if (i > 0) { 76 line = line.substring(0, i); 77 } 78 // Everything ending with a '/' has already been stripped but the remainder might start with "docker-" 79 if (line.contains("docker-")) { 80 // 8:cpuset:/kubepods.slice/kubepods-pod9c26dfb6_b9c9_11e7_bfb9_02c6c1fc4861.slice/docker-3dd988081e7149463c043b5d9c57d7309e079c5e9290f91feba1cc45a04d6a5b.scope 81 i = line.lastIndexOf("docker-"); 82 line = line.substring(i + 7); 83 } 84 return line.length() <= MAXLENGTH ? line : line.substring(0, MAXLENGTH); 85 } 86 87 return null; 88 } 89 }