Esempio n. 1
0
        /// <summary>
        /// Builds a <see cref="GkePlatformDetails"/> from the given metadata and kubernetes data.
        /// The metadata is normally retrieved from the GCE metadata server.
        /// The kubernetes data is normally retrieved using the kubernetes API.
        /// This method attempts to return as much information as it is present on <paramref name="metadataJson"/>
        /// and <paramref name="kubernetesData"/> but will return <see cref="string.Empty"/> for <see cref="GkePlatformDetails"/>
        /// properties whose corresponding information is corrupt or missing in <paramref name="metadataJson"/>
        /// or <paramref name="kubernetesData"/>.
        /// </summary>
        /// <param name="metadataJson">JSON metadata, normally retrieved from the GCE metadata server.
        /// Must not be <c>null</c>.</param>
        /// <param name="kubernetesData">Kubernetes data, normally retrieved using the kubernetes API.
        /// Must not be <c>null</c>.</param>
        /// <returns>A populated <see cref="GkePlatformDetails"/> if the metadata represents and GKE instance;
        /// <c>null</c> otherwise.</returns>
        public static GkePlatformDetails TryLoad(string metadataJson, KubernetesData kubernetesData)
        {
            GaxPreconditions.CheckNotNull(metadataJson, nameof(metadataJson));
            GaxPreconditions.CheckNotNull(kubernetesData, nameof(kubernetesData));
            JObject metadata      = null;
            JObject namespaceData = null;
            JObject podData       = null;

            // Parse JSON, ignoring all errors; partially available data is supported
            try { metadata = JObject.Parse(metadataJson); } catch { }
            try { namespaceData = JObject.Parse(kubernetesData.NamespaceJson); } catch { }
            try { podData = JObject.Parse(kubernetesData.PodJson); } catch { }
            if (metadata == null)
            {
                // Metadata is required. If it's not present, or the JSON cannot be parsed, return null.
                return(null);
            }
            if (namespaceData?["kind"]?.Value <string>() != "Namespace")
            {
                // If namespaceData looks corrupt/incomplete, ignore it.
                namespaceData = null;
            }
            if (podData?["kind"]?.Value <string>() != "Pod")
            {
                // If podData looks corrupt/incomplete, ignore it.
                podData = null;
            }
            var hostName        = kubernetesData.PodName ?? podData?["metadata"]?["name"]?.Value <string>() ?? ""; // Pod name is the hostname
            var projectId       = metadata["project"]?["projectId"]?.Value <string>();
            var clusterName     = metadata["instance"]?["attributes"]?["cluster-name"]?.Value <string>();
            var instanceId      = metadata["instance"]?["id"]?.Value <string>();
            var instanceZone    = metadata["instance"]?["zone"]?.Value <string>();
            var clusterLocation = metadata["instance"]?["attributes"]?["cluster-location"]?.Value <string>();
            var namespaceId     = namespaceData?["metadata"]?["name"]?.Value <string>() ?? kubernetesData.NamespaceName ?? "";
            var podId           = podData?["metadata"]?["name"]?.Value <string>() ?? kubernetesData.PodName ?? "";
            var podUid          = podData?["metadata"]?["uid"]?.Value <string>() ?? "";
            // A hack to find the container name. There appears to be no official way to do this.
            var regex          = new Regex($"/var/lib/kubelet/pods/{podUid}/containers/([^/]+)/.*/dev/termination-log");
            var containerNames = kubernetesData.MountInfo?.Select(x =>
            {
                var match = regex.Match(x);
                if (match.Success)
                {
                    return(match.Groups[1].Value);
                }
                return(null);
            }).Where(x => x != null).ToList();
            var containerName = containerNames?.Count == 1 ? containerNames[0] : "";

            if (hostName != null && projectId != null && clusterName != null && instanceId != null &&
                instanceZone != null && clusterLocation != null && namespaceId != null && podId != null && containerName != null)
            {
                if (Platform.s_zoneTemplate.TryParseName(instanceZone, out var instanceLocation))
                {
                    return(new GkePlatformDetails(metadataJson, projectId, clusterName, instanceLocation[1], hostName,
                                                  instanceId, instanceZone, namespaceId, podId, containerName, clusterLocation));
                }
            }
            return(null);
        }
Esempio n. 2
0
    private IKubernetes GetKubernetesClient(KubernetesData kubernetesData)
    {
        if (kubernetesData is null)
        {
            throw new ArgumentNullException(nameof(kubernetesData));
        }

        var kubernetesConfig = Yaml.LoadFromString <K8SConfiguration>(kubernetesData.Yaml);

        return(GetKubernetesClient(kubernetesConfig));
    }
Esempio n. 3
0
        /// <summary>
        /// Builds a <see cref="GkePlatformDetails"/> from the given metadata and kubernetes data.
        /// The metadata is normally retrieved from the GCE metadata server.
        /// The kubernetes data is normally retrieved using the kubernetes API.
        /// This method attempts to return as much information as it is present on <paramref name="metadataJson"/>
        /// and <paramref name="kubernetesData"/> but will return <see cref="string.Empty"/> for <see cref="GkePlatformDetails"/>
        /// properties whose corresponding information is corrupt or missing in <paramref name="metadataJson"/>
        /// or <paramref name="kubernetesData"/>.
        /// </summary>
        /// <param name="metadataJson">JSON metadata, normally retrieved from the GCE metadata server.
        /// Must not be <c>null</c>.</param>
        /// <param name="kubernetesData">Kubernetes data, normally retrieved using the kubernetes API.
        /// Must not be <c>null</c>.</param>
        /// <returns>A populated <see cref="GkePlatformDetails"/> if the metadata represents and GKE instance;
        /// <c>null</c> otherwise.</returns>
        public static GkePlatformDetails TryLoad(string metadataJson, KubernetesData kubernetesData)
        {
            GaxPreconditions.CheckNotNull(metadataJson, nameof(metadataJson));
            GaxPreconditions.CheckNotNull(kubernetesData, nameof(kubernetesData));
            JObject metadata      = null;
            JObject namespaceData = null;
            JObject podData       = null;

            // Parse JSON, ignoring all errors; partially available data is supported
            try { metadata = JObject.Parse(metadataJson); } catch { }
            try { namespaceData = JObject.Parse(kubernetesData.NamespaceJson); } catch { }
            try { podData = JObject.Parse(kubernetesData.PodJson); } catch { }
            if (metadata == null)
            {
                // Metadata is required. If it's not present, or the JSON cannot be parsed, return null.
                return(null);
            }
            if (namespaceData?["kind"]?.Value <string>() != "Namespace")
            {
                // If namespaceData looks corrupt/incomplete, ignore it.
                namespaceData = null;
            }
            if (podData?["kind"]?.Value <string>() != "Pod")
            {
                // If podData looks corrupt/incomplete, ignore it.
                podData = null;
            }
            var hostName        = kubernetesData.PodName ?? podData?["metadata"]?["name"]?.Value <string>() ?? ""; // Pod name is the hostname
            var projectId       = metadata["project"]?["projectId"]?.Value <string>();
            var clusterName     = metadata["instance"]?["attributes"]?["cluster-name"]?.Value <string>();
            var instanceId      = metadata["instance"]?["id"]?.Value <string>();
            var instanceZone    = metadata["instance"]?["zone"]?.Value <string>();
            var clusterLocation = metadata["instance"]?["attributes"]?["cluster-location"]?.Value <string>();
            var namespaceId     = namespaceData?["metadata"]?["name"]?.Value <string>() ?? kubernetesData.NamespaceName ?? "";
            var podId           = podData?["metadata"]?["name"]?.Value <string>() ?? kubernetesData.PodName ?? "";

            // Note: unlike other variables, we keep null as null here - we're not propagating it anywhere beyond the DeriveContainerName method.
            var podUid        = podData?["metadata"]?["uid"]?.Value <string>();
            var containerName = DeriveContainerName(podUid, kubernetesData.MountInfo) ?? "";

            if (hostName != null && projectId != null && clusterName != null && instanceId != null &&
                instanceZone != null && clusterLocation != null && namespaceId != null && podId != null && containerName != null)
            {
                if (Platform.s_zoneTemplate.TryParseName(instanceZone, out var instanceLocation))
                {
                    return(new GkePlatformDetails(metadataJson, projectId, clusterName, instanceLocation[1], hostName,
                                                  instanceId, instanceZone, namespaceId, podId, containerName, clusterLocation));
                }
            }
            return(null);
        }