From 43355a6028d7c8a1fdf9753da21843949460c8e8 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Fri, 2 Jul 2021 13:42:58 -0700 Subject: [PATCH 01/33] linux build speed improvements --- kubernetes/linux/Dockerfile | 5 ++-- kubernetes/linux/setup.sh | 55 +++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/kubernetes/linux/Dockerfile b/kubernetes/linux/Dockerfile index 1ae7bef61..ceb7a8848 100644 --- a/kubernetes/linux/Dockerfile +++ b/kubernetes/linux/Dockerfile @@ -16,14 +16,15 @@ ENV AZMON_COLLECT_ENV False ENV KUBE_CLIENT_BACKOFF_BASE 1 ENV KUBE_CLIENT_BACKOFF_DURATION 0 ENV RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR 0.9 -RUN /usr/bin/apt-get update && /usr/bin/apt-get install -y libc-bin wget openssl curl sudo python-ctypes init-system-helpers net-tools rsyslog cron vim dmidecode apt-transport-https gnupg && rm -rf /var/lib/apt/lists/* COPY setup.sh main.sh defaultpromenvvariables defaultpromenvvariables-rs defaultpromenvvariables-sidecar mdsd.xml envmdsd $tmpdir/ WORKDIR ${tmpdir} +RUN chmod 775 $tmpdir/*.sh; sync; $tmpdir/setup.sh + # copy docker provider shell bundle to use the agent image COPY ./Linux_ULINUX_1.0_x64_64_Release/docker-cimprov-*.*.*-*.x86_64.sh . # Note: If you prefer remote destination, uncomment below line and comment above line # wget https://github.com/microsoft/Docker-Provider/releases/download/10.0.0-1/docker-cimprov-10.0.0-1.universal.x86_64.sh +RUN /bin/bash -c "/opt/docker-cimprov-*.*.*-*.x86_64.sh --install && rm -f /opt/docker-cimprov*.sh" -RUN chmod 775 $tmpdir/*.sh; sync; $tmpdir/setup.sh CMD [ "/opt/main.sh" ] diff --git a/kubernetes/linux/setup.sh b/kubernetes/linux/setup.sh index ad7cc2232..d4788350a 100644 --- a/kubernetes/linux/setup.sh +++ b/kubernetes/linux/setup.sh @@ -1,9 +1,26 @@ -TMPDIR="/opt" -cd $TMPDIR +cd /opt + +# install ruby2.6 +sudo apt-get install software-properties-common -y +sudo apt-add-repository ppa:brightbox/ruby-ng -y +#fluent-bit(td-agent-bit) +wget -qO - https://packages.fluentbit.io/fluentbit.key | sudo apt-key add - +sudo echo "deb https://packages.fluentbit.io/ubuntu/xenial xenial main" >> /etc/apt/sources.list +sudo apt-get update + +apt-get install -y libc-bin wget openssl curl sudo python-ctypes init-system-helpers net-tools rsyslog cron vim dmidecode apt-transport-https gnupg + +# install telegraf in parallel with everything else to save build time +( + wget https://dl.influxdata.com/telegraf/releases/telegraf-1.18.0_linux_amd64.tar.gz + tar -zxvf telegraf-1.18.0_linux_amd64.tar.gz + mv /opt/telegraf-1.18.0/usr/bin/telegraf /opt/telegraf + chmod 777 /opt/telegraf +) & #Download utf-8 encoding capability on the omsagent container. #upgrade apt to latest version -apt-get update && apt-get install -y apt && DEBIAN_FRONTEND=noninteractive apt-get install -y locales +apt-get install -y apt && DEBIAN_FRONTEND=noninteractive apt-get install -y locales sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ dpkg-reconfigure --frontend=noninteractive locales && \ @@ -12,12 +29,11 @@ sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ #install oneagent - Official bits (05/17/2021) wget https://github.com/microsoft/Docker-Provider/releases/download/05172021-oneagent/azure-mdsd_1.10.1-build.master.213_x86_64.deb -/usr/bin/dpkg -i $TMPDIR/azure-mdsd*.deb -cp -f $TMPDIR/mdsd.xml /etc/mdsd.d -cp -f $TMPDIR/envmdsd /etc/mdsd.d +/usr/bin/dpkg -i /opt/azure-mdsd*.deb +cp -f /opt/mdsd.xml /etc/mdsd.d +cp -f /opt/envmdsd /etc/mdsd.d #download inotify tools for watching configmap changes -sudo apt-get update sudo apt-get install inotify-tools -y #used to parse response of kubelet apis @@ -27,26 +43,10 @@ sudo apt-get install jq=1.5+dfsg-2 -y #used to setcaps for ruby process to read /proc/env sudo apt-get install libcap2-bin -y -wget https://dl.influxdata.com/telegraf/releases/telegraf-1.18.0_linux_amd64.tar.gz -tar -zxvf telegraf-1.18.0_linux_amd64.tar.gz - -mv /opt/telegraf-1.18.0/usr/bin/telegraf /opt/telegraf - -chmod 777 /opt/telegraf - -# Use wildcard version so that it doesnt require to touch this file -/$TMPDIR/docker-cimprov-*.*.*-*.x86_64.sh --install - #download and install fluent-bit(td-agent-bit) -wget -qO - https://packages.fluentbit.io/fluentbit.key | sudo apt-key add - -sudo echo "deb https://packages.fluentbit.io/ubuntu/xenial xenial main" >> /etc/apt/sources.list -sudo apt-get update sudo apt-get install td-agent-bit=1.6.8 -y # install ruby2.6 -sudo apt-get install software-properties-common -y -sudo apt-add-repository ppa:brightbox/ruby-ng -y -sudo apt-get update sudo apt-get install ruby2.6 ruby2.6-dev gcc make -y # fluentd v1 gem gem install fluentd -v "1.12.2" --no-document @@ -54,10 +54,9 @@ fluentd --setup ./fluent gem install gyoku iso8601 --no-doc -rm -f $TMPDIR/docker-cimprov*.sh -rm -f $TMPDIR/azure-mdsd*.deb -rm -f $TMPDIR/mdsd.xml -rm -f $TMPDIR/envmdsd +rm -f /opt/azure-mdsd*.deb +rm -f /opt/mdsd.xml +rm -f /opt/envmdsd # Remove settings for cron.daily that conflict with the node's cron.daily. Since both are trying to rotate the same files # in /var/log at the same time, the rotation doesn't happen correctly and then the *.1 file is forever logged to. @@ -70,3 +69,5 @@ if [ -e "/var/lib/gems/2.6.0/gems/http_parser.rb-0.6.0/Gemfile.lock" ]; then echo "Renaming unused gemfile.lock for http_parser 0.6.0" mv /var/lib/gems/2.6.0/gems/http_parser.rb-0.6.0/Gemfile.lock /var/lib/gems/2.6.0/gems/http_parser.rb-0.6.0/renamed_Gemfile_lock.renamed fi + +wait # in case telegraf hasn't finished installing yet \ No newline at end of file From fd61e505bef64814579f6a2d54c33110bb6f1582 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Fri, 2 Jul 2021 13:48:17 -0700 Subject: [PATCH 02/33] small changes --- kubernetes/linux/setup.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kubernetes/linux/setup.sh b/kubernetes/linux/setup.sh index d4788350a..059a166e7 100644 --- a/kubernetes/linux/setup.sh +++ b/kubernetes/linux/setup.sh @@ -1,11 +1,12 @@ cd /opt -# install ruby2.6 +# set up apt repo for ruby2.6 sudo apt-get install software-properties-common -y sudo apt-add-repository ppa:brightbox/ruby-ng -y -#fluent-bit(td-agent-bit) +# set up apt repo for fluent-bit(td-agent-bit) wget -qO - https://packages.fluentbit.io/fluentbit.key | sudo apt-key add - sudo echo "deb https://packages.fluentbit.io/ubuntu/xenial xenial main" >> /etc/apt/sources.list + sudo apt-get update apt-get install -y libc-bin wget openssl curl sudo python-ctypes init-system-helpers net-tools rsyslog cron vim dmidecode apt-transport-https gnupg @@ -70,4 +71,4 @@ if [ -e "/var/lib/gems/2.6.0/gems/http_parser.rb-0.6.0/Gemfile.lock" ]; then mv /var/lib/gems/2.6.0/gems/http_parser.rb-0.6.0/Gemfile.lock /var/lib/gems/2.6.0/gems/http_parser.rb-0.6.0/renamed_Gemfile_lock.renamed fi -wait # in case telegraf hasn't finished installing yet \ No newline at end of file +wait # in case telegraf hasn't finished installing yet From f0f3cf7403db97a6f65f696753a6599f79ea7722 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Wed, 7 Jul 2021 16:54:32 -0700 Subject: [PATCH 03/33] added protection against node json with missing data --- source/plugins/ruby/in_kube_nodes.rb | 74 +++++++++++++++------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/source/plugins/ruby/in_kube_nodes.rb b/source/plugins/ruby/in_kube_nodes.rb index ebfa903fd..5101876d2 100644 --- a/source/plugins/ruby/in_kube_nodes.rb +++ b/source/plugins/ruby/in_kube_nodes.rb @@ -280,48 +280,54 @@ def parse_and_emit_records(nodeInventory, batchTime = Time.utc.iso8601) timeDifference = (DateTime.now.to_time.to_i - @@nodeTelemetryTimeTracker).abs timeDifferenceInMinutes = timeDifference / 60 if (timeDifferenceInMinutes >= Constants::TELEMETRY_FLUSH_INTERVAL_IN_MINUTES) - properties = getNodeTelemetryProps(item) - properties["KubernetesProviderID"] = nodeInventoryRecord["KubernetesProviderID"] - capacityInfo = item["status"]["capacity"] - - ApplicationInsightsUtility.sendMetricTelemetry("NodeMemory", capacityInfo["memory"], properties) begin - if (!capacityInfo["nvidia.com/gpu"].nil?) && (!capacityInfo["nvidia.com/gpu"].empty?) - properties["nvigpus"] = capacityInfo["nvidia.com/gpu"] + properties = getNodeTelemetryProps(item) + properties["KubernetesProviderID"] = nodeInventoryRecord["KubernetesProviderID"] + capacityInfo = item["status"]["capacity"] + + ApplicationInsightsUtility.sendMetricTelemetry("NodeMemory", capacityInfo["memory"], properties) + begin + if (!capacityInfo["nvidia.com/gpu"].nil?) && (!capacityInfo["nvidia.com/gpu"].empty?) + properties["nvigpus"] = capacityInfo["nvidia.com/gpu"] + end + + if (!capacityInfo["amd.com/gpu"].nil?) && (!capacityInfo["amd.com/gpu"].empty?) + properties["amdgpus"] = capacityInfo["amd.com/gpu"] + end + rescue => errorStr + $log.warn "Failed in getting GPU telemetry in_kube_nodes : #{errorStr}" + $log.debug_backtrace(errorStr.backtrace) + ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) + end + + # Telemetry for data collection config for replicaset + if (File.file?(@@configMapMountPath)) + properties["collectAllKubeEvents"] = @@collectAllKubeEvents end - if (!capacityInfo["amd.com/gpu"].nil?) && (!capacityInfo["amd.com/gpu"].empty?) - properties["amdgpus"] = capacityInfo["amd.com/gpu"] + #telemetry about prometheus metric collections settings for replicaset + if (File.file?(@@promConfigMountPath)) + properties["rsPromInt"] = @@rsPromInterval + properties["rsPromFPC"] = @@rsPromFieldPassCount + properties["rsPromFDC"] = @@rsPromFieldDropCount + properties["rsPromServ"] = @@rsPromK8sServiceCount + properties["rsPromUrl"] = @@rsPromUrlCount + properties["rsPromMonPods"] = @@rsPromMonitorPods + properties["rsPromMonPodsNs"] = @@rsPromMonitorPodsNamespaceLength + properties["rsPromMonPodsLabelSelectorLength"] = @@rsPromMonitorPodsLabelSelectorLength + properties["rsPromMonPodsFieldSelectorLength"] = @@rsPromMonitorPodsFieldSelectorLength end + # telemetry about osm metric settings for replicaset + if (File.file?(@@osmConfigMountPath)) + properties["osmNamespaceCount"] = @@osmNamespaceCount + end + ApplicationInsightsUtility.sendMetricTelemetry("NodeCoreCapacity", capacityInfo["cpu"], properties) + telemetrySent = true rescue => errorStr - $log.warn "Failed in getting GPU telemetry in_kube_nodes : #{errorStr}" + $log.warn "Failed in getting telemetry in_kube_nodes : #{errorStr}" $log.debug_backtrace(errorStr.backtrace) ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) end - - # Telemetry for data collection config for replicaset - if (File.file?(@@configMapMountPath)) - properties["collectAllKubeEvents"] = @@collectAllKubeEvents - end - - #telemetry about prometheus metric collections settings for replicaset - if (File.file?(@@promConfigMountPath)) - properties["rsPromInt"] = @@rsPromInterval - properties["rsPromFPC"] = @@rsPromFieldPassCount - properties["rsPromFDC"] = @@rsPromFieldDropCount - properties["rsPromServ"] = @@rsPromK8sServiceCount - properties["rsPromUrl"] = @@rsPromUrlCount - properties["rsPromMonPods"] = @@rsPromMonitorPods - properties["rsPromMonPodsNs"] = @@rsPromMonitorPodsNamespaceLength - properties["rsPromMonPodsLabelSelectorLength"] = @@rsPromMonitorPodsLabelSelectorLength - properties["rsPromMonPodsFieldSelectorLength"] = @@rsPromMonitorPodsFieldSelectorLength - end - # telemetry about osm metric settings for replicaset - if (File.file?(@@osmConfigMountPath)) - properties["osmNamespaceCount"] = @@osmNamespaceCount - end - ApplicationInsightsUtility.sendMetricTelemetry("NodeCoreCapacity", capacityInfo["cpu"], properties) - telemetrySent = true end end if telemetrySent == true From e6a5e4b00f99dfaadb01a52042d2e30194b3d9b7 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Thu, 8 Jul 2021 16:28:35 -0700 Subject: [PATCH 04/33] fixed build speedups --- kubernetes/linux/Dockerfile | 6 +++--- kubernetes/linux/setup.sh | 10 +++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/kubernetes/linux/Dockerfile b/kubernetes/linux/Dockerfile index ceb7a8848..1b230f0cb 100644 --- a/kubernetes/linux/Dockerfile +++ b/kubernetes/linux/Dockerfile @@ -16,15 +16,15 @@ ENV AZMON_COLLECT_ENV False ENV KUBE_CLIENT_BACKOFF_BASE 1 ENV KUBE_CLIENT_BACKOFF_DURATION 0 ENV RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR 0.9 -COPY setup.sh main.sh defaultpromenvvariables defaultpromenvvariables-rs defaultpromenvvariables-sidecar mdsd.xml envmdsd $tmpdir/ +COPY setup.sh mdsd.xml envmdsd $tmpdir/ WORKDIR ${tmpdir} RUN chmod 775 $tmpdir/*.sh; sync; $tmpdir/setup.sh # copy docker provider shell bundle to use the agent image +COPY main.sh defaultpromenvvariables defaultpromenvvariables-rs defaultpromenvvariables-sidecar $tmpdir/ COPY ./Linux_ULINUX_1.0_x64_64_Release/docker-cimprov-*.*.*-*.x86_64.sh . # Note: If you prefer remote destination, uncomment below line and comment above line # wget https://github.com/microsoft/Docker-Provider/releases/download/10.0.0-1/docker-cimprov-10.0.0-1.universal.x86_64.sh -RUN /bin/bash -c "/opt/docker-cimprov-*.*.*-*.x86_64.sh --install && rm -f /opt/docker-cimprov*.sh" - +RUN /bin/bash -c "/opt/docker-cimprov-*.*.*-*.x86_64.sh --install && rm -f /opt/docker-cimprov*.sh; chmod 775 $tmpdir/*.sh" CMD [ "/opt/main.sh" ] diff --git a/kubernetes/linux/setup.sh b/kubernetes/linux/setup.sh index 059a166e7..bec74a69f 100644 --- a/kubernetes/linux/setup.sh +++ b/kubernetes/linux/setup.sh @@ -1,15 +1,19 @@ +set -e # exit if any command exits with an error + cd /opt +apt-get update +apt-get install -y libc-bin wget openssl curl sudo python-ctypes init-system-helpers net-tools rsyslog cron vim dmidecode apt-transport-https gnupg + # set up apt repo for ruby2.6 sudo apt-get install software-properties-common -y sudo apt-add-repository ppa:brightbox/ruby-ng -y # set up apt repo for fluent-bit(td-agent-bit) wget -qO - https://packages.fluentbit.io/fluentbit.key | sudo apt-key add - -sudo echo "deb https://packages.fluentbit.io/ubuntu/xenial xenial main" >> /etc/apt/sources.list +echo "deb https://packages.fluentbit.io/ubuntu/xenial xenial main" >> /etc/apt/sources.list -sudo apt-get update +apt-get update -apt-get install -y libc-bin wget openssl curl sudo python-ctypes init-system-helpers net-tools rsyslog cron vim dmidecode apt-transport-https gnupg # install telegraf in parallel with everything else to save build time ( From f9fd5705cc213e75fda1666382bc4a1e93636879 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Thu, 8 Jul 2021 16:29:21 -0700 Subject: [PATCH 05/33] Revert "fixed build speedups" This reverts commit e6a5e4b00f99dfaadb01a52042d2e30194b3d9b7. --- kubernetes/linux/Dockerfile | 6 +++--- kubernetes/linux/setup.sh | 10 +++------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/kubernetes/linux/Dockerfile b/kubernetes/linux/Dockerfile index 1b230f0cb..ceb7a8848 100644 --- a/kubernetes/linux/Dockerfile +++ b/kubernetes/linux/Dockerfile @@ -16,15 +16,15 @@ ENV AZMON_COLLECT_ENV False ENV KUBE_CLIENT_BACKOFF_BASE 1 ENV KUBE_CLIENT_BACKOFF_DURATION 0 ENV RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR 0.9 -COPY setup.sh mdsd.xml envmdsd $tmpdir/ +COPY setup.sh main.sh defaultpromenvvariables defaultpromenvvariables-rs defaultpromenvvariables-sidecar mdsd.xml envmdsd $tmpdir/ WORKDIR ${tmpdir} RUN chmod 775 $tmpdir/*.sh; sync; $tmpdir/setup.sh # copy docker provider shell bundle to use the agent image -COPY main.sh defaultpromenvvariables defaultpromenvvariables-rs defaultpromenvvariables-sidecar $tmpdir/ COPY ./Linux_ULINUX_1.0_x64_64_Release/docker-cimprov-*.*.*-*.x86_64.sh . # Note: If you prefer remote destination, uncomment below line and comment above line # wget https://github.com/microsoft/Docker-Provider/releases/download/10.0.0-1/docker-cimprov-10.0.0-1.universal.x86_64.sh -RUN /bin/bash -c "/opt/docker-cimprov-*.*.*-*.x86_64.sh --install && rm -f /opt/docker-cimprov*.sh; chmod 775 $tmpdir/*.sh" +RUN /bin/bash -c "/opt/docker-cimprov-*.*.*-*.x86_64.sh --install && rm -f /opt/docker-cimprov*.sh" + CMD [ "/opt/main.sh" ] diff --git a/kubernetes/linux/setup.sh b/kubernetes/linux/setup.sh index bec74a69f..059a166e7 100644 --- a/kubernetes/linux/setup.sh +++ b/kubernetes/linux/setup.sh @@ -1,19 +1,15 @@ -set -e # exit if any command exits with an error - cd /opt -apt-get update -apt-get install -y libc-bin wget openssl curl sudo python-ctypes init-system-helpers net-tools rsyslog cron vim dmidecode apt-transport-https gnupg - # set up apt repo for ruby2.6 sudo apt-get install software-properties-common -y sudo apt-add-repository ppa:brightbox/ruby-ng -y # set up apt repo for fluent-bit(td-agent-bit) wget -qO - https://packages.fluentbit.io/fluentbit.key | sudo apt-key add - -echo "deb https://packages.fluentbit.io/ubuntu/xenial xenial main" >> /etc/apt/sources.list +sudo echo "deb https://packages.fluentbit.io/ubuntu/xenial xenial main" >> /etc/apt/sources.list -apt-get update +sudo apt-get update +apt-get install -y libc-bin wget openssl curl sudo python-ctypes init-system-helpers net-tools rsyslog cron vim dmidecode apt-transport-https gnupg # install telegraf in parallel with everything else to save build time ( From f83ce831f7fae45e516b36a109b0a0ce5b6308e1 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Thu, 8 Jul 2021 16:30:27 -0700 Subject: [PATCH 06/33] Revert "Merge branch 'david/faster_builds' into david/malformed-node-fix" This reverts commit e54ecf9ea852f498d85187224c889a2a794724ca, reversing changes made to f0f3cf7403db97a6f65f696753a6599f79ea7722. --- kubernetes/linux/Dockerfile | 5 ++-- kubernetes/linux/setup.sh | 56 ++++++++++++++++++------------------- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/kubernetes/linux/Dockerfile b/kubernetes/linux/Dockerfile index ceb7a8848..1ae7bef61 100644 --- a/kubernetes/linux/Dockerfile +++ b/kubernetes/linux/Dockerfile @@ -16,15 +16,14 @@ ENV AZMON_COLLECT_ENV False ENV KUBE_CLIENT_BACKOFF_BASE 1 ENV KUBE_CLIENT_BACKOFF_DURATION 0 ENV RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR 0.9 +RUN /usr/bin/apt-get update && /usr/bin/apt-get install -y libc-bin wget openssl curl sudo python-ctypes init-system-helpers net-tools rsyslog cron vim dmidecode apt-transport-https gnupg && rm -rf /var/lib/apt/lists/* COPY setup.sh main.sh defaultpromenvvariables defaultpromenvvariables-rs defaultpromenvvariables-sidecar mdsd.xml envmdsd $tmpdir/ WORKDIR ${tmpdir} -RUN chmod 775 $tmpdir/*.sh; sync; $tmpdir/setup.sh - # copy docker provider shell bundle to use the agent image COPY ./Linux_ULINUX_1.0_x64_64_Release/docker-cimprov-*.*.*-*.x86_64.sh . # Note: If you prefer remote destination, uncomment below line and comment above line # wget https://github.com/microsoft/Docker-Provider/releases/download/10.0.0-1/docker-cimprov-10.0.0-1.universal.x86_64.sh -RUN /bin/bash -c "/opt/docker-cimprov-*.*.*-*.x86_64.sh --install && rm -f /opt/docker-cimprov*.sh" +RUN chmod 775 $tmpdir/*.sh; sync; $tmpdir/setup.sh CMD [ "/opt/main.sh" ] diff --git a/kubernetes/linux/setup.sh b/kubernetes/linux/setup.sh index 059a166e7..ad7cc2232 100644 --- a/kubernetes/linux/setup.sh +++ b/kubernetes/linux/setup.sh @@ -1,27 +1,9 @@ -cd /opt - -# set up apt repo for ruby2.6 -sudo apt-get install software-properties-common -y -sudo apt-add-repository ppa:brightbox/ruby-ng -y -# set up apt repo for fluent-bit(td-agent-bit) -wget -qO - https://packages.fluentbit.io/fluentbit.key | sudo apt-key add - -sudo echo "deb https://packages.fluentbit.io/ubuntu/xenial xenial main" >> /etc/apt/sources.list - -sudo apt-get update - -apt-get install -y libc-bin wget openssl curl sudo python-ctypes init-system-helpers net-tools rsyslog cron vim dmidecode apt-transport-https gnupg - -# install telegraf in parallel with everything else to save build time -( - wget https://dl.influxdata.com/telegraf/releases/telegraf-1.18.0_linux_amd64.tar.gz - tar -zxvf telegraf-1.18.0_linux_amd64.tar.gz - mv /opt/telegraf-1.18.0/usr/bin/telegraf /opt/telegraf - chmod 777 /opt/telegraf -) & +TMPDIR="/opt" +cd $TMPDIR #Download utf-8 encoding capability on the omsagent container. #upgrade apt to latest version -apt-get install -y apt && DEBIAN_FRONTEND=noninteractive apt-get install -y locales +apt-get update && apt-get install -y apt && DEBIAN_FRONTEND=noninteractive apt-get install -y locales sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ dpkg-reconfigure --frontend=noninteractive locales && \ @@ -30,11 +12,12 @@ sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ #install oneagent - Official bits (05/17/2021) wget https://github.com/microsoft/Docker-Provider/releases/download/05172021-oneagent/azure-mdsd_1.10.1-build.master.213_x86_64.deb -/usr/bin/dpkg -i /opt/azure-mdsd*.deb -cp -f /opt/mdsd.xml /etc/mdsd.d -cp -f /opt/envmdsd /etc/mdsd.d +/usr/bin/dpkg -i $TMPDIR/azure-mdsd*.deb +cp -f $TMPDIR/mdsd.xml /etc/mdsd.d +cp -f $TMPDIR/envmdsd /etc/mdsd.d #download inotify tools for watching configmap changes +sudo apt-get update sudo apt-get install inotify-tools -y #used to parse response of kubelet apis @@ -44,10 +27,26 @@ sudo apt-get install jq=1.5+dfsg-2 -y #used to setcaps for ruby process to read /proc/env sudo apt-get install libcap2-bin -y +wget https://dl.influxdata.com/telegraf/releases/telegraf-1.18.0_linux_amd64.tar.gz +tar -zxvf telegraf-1.18.0_linux_amd64.tar.gz + +mv /opt/telegraf-1.18.0/usr/bin/telegraf /opt/telegraf + +chmod 777 /opt/telegraf + +# Use wildcard version so that it doesnt require to touch this file +/$TMPDIR/docker-cimprov-*.*.*-*.x86_64.sh --install + #download and install fluent-bit(td-agent-bit) +wget -qO - https://packages.fluentbit.io/fluentbit.key | sudo apt-key add - +sudo echo "deb https://packages.fluentbit.io/ubuntu/xenial xenial main" >> /etc/apt/sources.list +sudo apt-get update sudo apt-get install td-agent-bit=1.6.8 -y # install ruby2.6 +sudo apt-get install software-properties-common -y +sudo apt-add-repository ppa:brightbox/ruby-ng -y +sudo apt-get update sudo apt-get install ruby2.6 ruby2.6-dev gcc make -y # fluentd v1 gem gem install fluentd -v "1.12.2" --no-document @@ -55,9 +54,10 @@ fluentd --setup ./fluent gem install gyoku iso8601 --no-doc -rm -f /opt/azure-mdsd*.deb -rm -f /opt/mdsd.xml -rm -f /opt/envmdsd +rm -f $TMPDIR/docker-cimprov*.sh +rm -f $TMPDIR/azure-mdsd*.deb +rm -f $TMPDIR/mdsd.xml +rm -f $TMPDIR/envmdsd # Remove settings for cron.daily that conflict with the node's cron.daily. Since both are trying to rotate the same files # in /var/log at the same time, the rotation doesn't happen correctly and then the *.1 file is forever logged to. @@ -70,5 +70,3 @@ if [ -e "/var/lib/gems/2.6.0/gems/http_parser.rb-0.6.0/Gemfile.lock" ]; then echo "Renaming unused gemfile.lock for http_parser 0.6.0" mv /var/lib/gems/2.6.0/gems/http_parser.rb-0.6.0/Gemfile.lock /var/lib/gems/2.6.0/gems/http_parser.rb-0.6.0/renamed_Gemfile_lock.renamed fi - -wait # in case telegraf hasn't finished installing yet From 95edf55364a294b9032fa9bd972d09f9b18f60f2 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Wed, 11 Aug 2021 14:28:23 -0700 Subject: [PATCH 07/33] initial snapshot --- .../installer/datafiles/base_container.data | 9 +- source/plugins/go/src/utils_test.go | 32 +++++ .../plugins/ruby/CAdvisorMetricsAPIClient.rb | 4 +- source/plugins/ruby/CustomMetricsUtils.rb | 8 +- source/plugins/ruby/KubernetesApiClient.rb | 34 ++--- source/plugins/ruby/MdmMetricsGenerator.rb | 17 +-- source/plugins/ruby/constants.rb | 4 +- source/plugins/{utils => ruby}/extension.rb | 0 .../{utils => ruby}/extension_utils.rb | 0 source/plugins/ruby/filter_cadvisor2mdm.rb | 126 ++++++++++-------- .../plugins/ruby/filter_cadvisor2mdm_test.rb | 115 ++++++++++++++++ source/plugins/ruby/kubelet_utils.rb | 4 +- source/plugins/ruby/mdm_metrics_generator.log | 1 + source/plugins/{utils => ruby}/oms_common.rb | 0 source/plugins/{utils => ruby}/omslog.rb | 0 source/plugins/ruby/test_registry.rb | 16 +++ test/unit-tests/run_go_tests.sh | 5 + test/unit-tests/run_ruby_tests.sh | 5 + 18 files changed, 286 insertions(+), 94 deletions(-) create mode 100644 source/plugins/go/src/utils_test.go rename source/plugins/{utils => ruby}/extension.rb (100%) rename source/plugins/{utils => ruby}/extension_utils.rb (100%) create mode 100644 source/plugins/ruby/filter_cadvisor2mdm_test.rb create mode 100644 source/plugins/ruby/mdm_metrics_generator.log rename source/plugins/{utils => ruby}/oms_common.rb (100%) rename source/plugins/{utils => ruby}/omslog.rb (100%) create mode 100644 source/plugins/ruby/test_registry.rb create mode 100755 test/unit-tests/run_go_tests.sh create mode 100644 test/unit-tests/run_ruby_tests.sh diff --git a/build/linux/installer/datafiles/base_container.data b/build/linux/installer/datafiles/base_container.data index b71cafd49..152a7f47a 100644 --- a/build/linux/installer/datafiles/base_container.data +++ b/build/linux/installer/datafiles/base_container.data @@ -148,10 +148,10 @@ MAINTAINER: 'Microsoft Corporation' /etc/fluent/plugin/MdmMetricsGenerator.rb; source/plugins/ruby/MdmMetricsGenerator.rb; 644; root; root /etc/fluent/plugin/MdmAlertTemplates.rb; source/plugins/ruby/MdmAlertTemplates.rb; 644; root; root -/etc/fluent/plugin/omslog.rb; source/plugins/utils/omslog.rb; 644; root; root -/etc/fluent/plugin/oms_common.rb; source/plugins/utils/oms_common.rb; 644; root; root -/etc/fluent/plugin/extension.rb; source/plugins/utils/extension.rb; 644; root; root -/etc/fluent/plugin/extension_utils.rb; source/plugins/utils/extension_utils.rb; 644; root; root +/etc/fluent/plugin/omslog.rb; source/plugins/ruby/omslog.rb; 644; root; root +/etc/fluent/plugin/oms_common.rb; source/plugins/ruby/oms_common.rb; 644; root; root +/etc/fluent/plugin/extension.rb; source/plugins/ruby/extension.rb; 644; root; root +/etc/fluent/plugin/extension_utils.rb; source/plugins/ruby/extension_utils.rb; 644; root; root /etc/fluent/kube.conf; build/linux/installer/conf/kube.conf; 644; root; root @@ -172,6 +172,7 @@ MAINTAINER: 'Microsoft Corporation' /etc/fluent/plugin/filter_cadvisor_health_container.rb; source/plugins/ruby/filter_cadvisor_health_container.rb; 644; root; root /etc/fluent/plugin/filter_cadvisor_health_node.rb; source/plugins/ruby/filter_cadvisor_health_node.rb; 644; root; root /etc/fluent/plugin/filter_cadvisor2mdm.rb; source/plugins/ruby/filter_cadvisor2mdm.rb; 644; root; root +/etc/fluent/plugin/filter_cadvisor2mdm_test.rb; source/plugins/ruby/filter_cadvisor2mdm_test.rb; 644; root; root /etc/fluent/plugin/filter_health_model_builder.rb; source/plugins/ruby/filter_health_model_builder.rb; 644; root; root /etc/fluent/plugin/filter_inventory2mdm.rb; source/plugins/ruby/filter_inventory2mdm.rb; 644; root; root /etc/fluent/plugin/filter_telegraf2mdm.rb; source/plugins/ruby/filter_telegraf2mdm.rb; 644; root; root diff --git a/source/plugins/go/src/utils_test.go b/source/plugins/go/src/utils_test.go new file mode 100644 index 000000000..8d957267f --- /dev/null +++ b/source/plugins/go/src/utils_test.go @@ -0,0 +1,32 @@ +package main + +import ( + "testing" +) + +func Test_isValidUrl(t *testing.T) { + type test_struct struct { + isValid bool + url string + } + + tests := []test_struct{ + {true, "https://www.microsoft.com"}, + {true, "http://abc.xyz"}, + {true, "https://www.microsoft.com/tests"}, + {false, "()"}, + {false, "https//www.microsoft.com"}, + {false, "https:/www.microsoft.com"}, + {false, "https:/www.microsoft.com*"}, + {false, ""}, + } + + for _, tt := range tests { + t.Run(tt.url, func(t *testing.T) { + got := isValidUrl(tt.url) + if got != tt.isValid { + t.Errorf("isValidUrl(%s) = %t, want %t", tt.url, got, tt.isValid) + } + }) + } +} diff --git a/source/plugins/ruby/CAdvisorMetricsAPIClient.rb b/source/plugins/ruby/CAdvisorMetricsAPIClient.rb index da6e94f5f..017bfb08d 100644 --- a/source/plugins/ruby/CAdvisorMetricsAPIClient.rb +++ b/source/plugins/ruby/CAdvisorMetricsAPIClient.rb @@ -40,9 +40,9 @@ class CAdvisorMetricsAPIClient @os_type = ENV["OS_TYPE"] if !@os_type.nil? && !@os_type.empty? && @os_type.strip.casecmp("windows") == 0 - @LogPath = "/etc/omsagentwindows/kubernetes_perf_log.txt" + @LogPath = Constants::WINDOWS_LOG_PATH + "kubernetes_perf_log.txt" else - @LogPath = "/var/opt/microsoft/docker-cimprov/log/kubernetes_perf_log.txt" + @LogPath = Constants::LINUX_LOG_PATH + "kubernetes_perf_log.txt" end @Log = Logger.new(@LogPath, 2, 10 * 1048576) #keep last 2 files, max log file size = 10M # @@rxBytesLast = nil diff --git a/source/plugins/ruby/CustomMetricsUtils.rb b/source/plugins/ruby/CustomMetricsUtils.rb index fd9290b78..63172e05a 100644 --- a/source/plugins/ruby/CustomMetricsUtils.rb +++ b/source/plugins/ruby/CustomMetricsUtils.rb @@ -1,15 +1,17 @@ #!/usr/local/bin/ruby # frozen_string_literal: true +require_relative "test_registry" + class CustomMetricsUtils def initialize end class << self def check_custom_metrics_availability - aks_region = ENV['AKS_REGION'] - aks_resource_id = ENV['AKS_RESOURCE_ID'] - aks_cloud_environment = ENV['CLOUD_ENVIRONMENT'] + aks_region = Test_registry.instance.env['AKS_REGION'] + aks_resource_id = Test_registry.instance.env['AKS_RESOURCE_ID'] + aks_cloud_environment = Test_registry.instance.env['CLOUD_ENVIRONMENT'] if aks_region.to_s.empty? || aks_resource_id.to_s.empty? return false # This will also take care of AKS-Engine Scenario. AKS_REGION/AKS_RESOURCE_ID is not set for AKS-Engine. Only ACS_RESOURCE_NAME is set end diff --git a/source/plugins/ruby/KubernetesApiClient.rb b/source/plugins/ruby/KubernetesApiClient.rb index 4b50e20d8..3187f4a32 100644 --- a/source/plugins/ruby/KubernetesApiClient.rb +++ b/source/plugins/ruby/KubernetesApiClient.rb @@ -12,6 +12,8 @@ class KubernetesApiClient require_relative "oms_common" require_relative "constants" + require_relative "test_registry" + @@ApiVersion = "v1" @@ApiVersionApps = "v1" @@ApiGroupApps = "apps" @@ -25,11 +27,11 @@ class KubernetesApiClient #@@IsValidRunningNode = nil #@@IsLinuxCluster = nil @@KubeSystemNamespace = "kube-system" - @os_type = ENV["OS_TYPE"] + @os_type = Test_registry.instance.env["OS_TYPE"] if !@os_type.nil? && !@os_type.empty? && @os_type.strip.casecmp("windows") == 0 - @LogPath = "/etc/omsagentwindows/kubernetes_client_log.txt" + @LogPath = Constants::WINDOWS_LOG_PATH + "kubernetes_client_log.txt" else - @LogPath = "/var/opt/microsoft/docker-cimprov/log/kubernetes_client_log.txt" + @LogPath = Constants::LINUX_LOG_PATH + "kubernetes_client_log.txt" end @Log = Logger.new(@LogPath, 2, 10 * 1048576) #keep last 2 files, max log file size = 10M @@TokenFileName = "/var/run/secrets/kubernetes.io/serviceaccount/token" @@ -88,8 +90,8 @@ def getTokenStr end def getClusterRegion - if ENV["AKS_REGION"] - return ENV["AKS_REGION"] + if Test_registry.instance.env["AKS_REGION"] + return Test_registry.instance.env["AKS_REGION"] else @Log.warn ("Kubernetes environment variable not set AKS_REGION. Unable to get cluster region.") return nil @@ -98,16 +100,16 @@ def getClusterRegion def getResourceUri(resource, api_group) begin - if ENV["KUBERNETES_SERVICE_HOST"] && ENV["KUBERNETES_PORT_443_TCP_PORT"] + if Test_registry.instance.env["KUBERNETES_SERVICE_HOST"] && Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"] if api_group.nil? - return "https://#{ENV["KUBERNETES_SERVICE_HOST"]}:#{ENV["KUBERNETES_PORT_443_TCP_PORT"]}/api/" + @@ApiVersion + "/" + resource + return "https://#{Test_registry.instance.env["KUBERNETES_SERVICE_HOST"]}:#{Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"]}/api/" + @@ApiVersion + "/" + resource elsif api_group == @@ApiGroupApps - return "https://#{ENV["KUBERNETES_SERVICE_HOST"]}:#{ENV["KUBERNETES_PORT_443_TCP_PORT"]}/apis/apps/" + @@ApiVersionApps + "/" + resource + return "https://#{Test_registry.instance.env["KUBERNETES_SERVICE_HOST"]}:#{Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"]}/apis/apps/" + @@ApiVersionApps + "/" + resource elsif api_group == @@ApiGroupHPA - return "https://#{ENV["KUBERNETES_SERVICE_HOST"]}:#{ENV["KUBERNETES_PORT_443_TCP_PORT"]}/apis/" + @@ApiGroupHPA + "/" + @@ApiVersionHPA + "/" + resource + return "https://#{Test_registry.instance.env["KUBERNETES_SERVICE_HOST"]}:#{Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"]}/apis/" + @@ApiGroupHPA + "/" + @@ApiVersionHPA + "/" + resource end else - @Log.warn ("Kubernetes environment variable not set KUBERNETES_SERVICE_HOST: #{ENV["KUBERNETES_SERVICE_HOST"]} KUBERNETES_PORT_443_TCP_PORT: #{ENV["KUBERNETES_PORT_443_TCP_PORT"]}. Unable to form resourceUri") + @Log.warn ("Kubernetes environment variable not set KUBERNETES_SERVICE_HOST: #{Test_registry.instance.env["KUBERNETES_SERVICE_HOST"]} KUBERNETES_PORT_443_TCP_PORT: #{Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"]}. Unable to form resourceUri") return nil end end @@ -118,11 +120,11 @@ def getClusterName @@ClusterName = "None" begin #try getting resource ID for aks - cluster = ENV["AKS_RESOURCE_ID"] + cluster = Test_registry.instance.env["AKS_RESOURCE_ID"] if cluster && !cluster.nil? && !cluster.empty? @@ClusterName = cluster.split("/").last else - cluster = ENV["ACS_RESOURCE_NAME"] + cluster = Test_registry.instance.env["ACS_RESOURCE_NAME"] if cluster && !cluster.nil? && !cluster.empty? @@ClusterName = cluster else @@ -155,7 +157,7 @@ def getClusterId # e.g. md5 digest is 128 bits = 32 character in hex. Get first 16 and get a guid, and the next 16 to get resource id @@ClusterId = getClusterName begin - cluster = ENV["AKS_RESOURCE_ID"] + cluster = Test_registry.instance.env["AKS_RESOURCE_ID"] if cluster && !cluster.nil? && !cluster.empty? @@ClusterId = cluster end @@ -780,10 +782,10 @@ def getResourcesAndContinuationToken(uri, api_group: nil) def getKubeAPIServerUrl apiServerUrl = nil begin - if ENV["KUBERNETES_SERVICE_HOST"] && ENV["KUBERNETES_PORT_443_TCP_PORT"] - apiServerUrl = "https://#{ENV["KUBERNETES_SERVICE_HOST"]}:#{ENV["KUBERNETES_PORT_443_TCP_PORT"]}" + if Test_registry.instance.env["KUBERNETES_SERVICE_HOST"] && Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"] + apiServerUrl = "https://#{Test_registry.instance.env["KUBERNETES_SERVICE_HOST"]}:#{Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"]}" else - @Log.warn "Kubernetes environment variable not set KUBERNETES_SERVICE_HOST: #{ENV["KUBERNETES_SERVICE_HOST"]} KUBERNETES_PORT_443_TCP_PORT: #{ENV["KUBERNETES_PORT_443_TCP_PORT"]}. Unable to form resourceUri" + @Log.warn "Kubernetes environment variable not set KUBERNETES_SERVICE_HOST: #{Test_registry.instance.env["KUBERNETES_SERVICE_HOST"]} KUBERNETES_PORT_443_TCP_PORT: #{Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"]}. Unable to form resourceUri" end rescue => errorStr @Log.warn "KubernetesApiClient::getKubeAPIServerUrl:Failed #{errorStr}" diff --git a/source/plugins/ruby/MdmMetricsGenerator.rb b/source/plugins/ruby/MdmMetricsGenerator.rb index 0858990da..93004688e 100644 --- a/source/plugins/ruby/MdmMetricsGenerator.rb +++ b/source/plugins/ruby/MdmMetricsGenerator.rb @@ -9,12 +9,13 @@ class MdmMetricsGenerator require_relative "ApplicationInsightsUtility" require_relative "constants" require_relative "oms_common" + require_relative "test_registry" - @os_type = ENV["OS_TYPE"] + @os_type = Test_registry.instance.env["OS_TYPE"] if !@os_type.nil? && !@os_type.empty? && @os_type.strip.casecmp("windows") == 0 - @log_path = "/etc/omsagentwindows/mdm_metrics_generator.log" + @log_path = Constants::WINDOWS_LOG_PATH + "mdm_metrics_generator.log" else - @log_path = "/var/opt/microsoft/docker-cimprov/log/mdm_metrics_generator.log" + @log_path = Constants::LINUX_LOG_PATH + "mdm_metrics_generator.log" end @log = Logger.new(@log_path, 1, 5000000) @@hostName = (OMS::Common.get_hostname) @@ -495,32 +496,32 @@ def getContainerResourceUtilizationThresholds metric_threshold_hash[Constants::PV_USED_BYTES] = Constants::DEFAULT_MDM_PV_UTILIZATION_THRESHOLD metric_threshold_hash[Constants::JOB_COMPLETION_TIME] = Constants::DEFAULT_MDM_JOB_COMPLETED_TIME_THRESHOLD_MINUTES - cpuThreshold = ENV["AZMON_ALERT_CONTAINER_CPU_THRESHOLD"] + cpuThreshold = Test_registry.instance.env["AZMON_ALERT_CONTAINER_CPU_THRESHOLD"] if !cpuThreshold.nil? && !cpuThreshold.empty? #Rounding this to 2 decimal places, since this value is user configurable cpuThresholdFloat = (cpuThreshold.to_f).round(2) metric_threshold_hash[Constants::CPU_USAGE_NANO_CORES] = cpuThresholdFloat end - memoryRssThreshold = ENV["AZMON_ALERT_CONTAINER_MEMORY_RSS_THRESHOLD"] + memoryRssThreshold = Test_registry.instance.env["AZMON_ALERT_CONTAINER_MEMORY_RSS_THRESHOLD"] if !memoryRssThreshold.nil? && !memoryRssThreshold.empty? memoryRssThresholdFloat = (memoryRssThreshold.to_f).round(2) metric_threshold_hash[Constants::MEMORY_RSS_BYTES] = memoryRssThresholdFloat end - memoryWorkingSetThreshold = ENV["AZMON_ALERT_CONTAINER_MEMORY_WORKING_SET_THRESHOLD"] + memoryWorkingSetThreshold = Test_registry.instance.env["AZMON_ALERT_CONTAINER_MEMORY_WORKING_SET_THRESHOLD"] if !memoryWorkingSetThreshold.nil? && !memoryWorkingSetThreshold.empty? memoryWorkingSetThresholdFloat = (memoryWorkingSetThreshold.to_f).round(2) metric_threshold_hash[Constants::MEMORY_WORKING_SET_BYTES] = memoryWorkingSetThresholdFloat end - pvUsagePercentageThreshold = ENV["AZMON_ALERT_PV_USAGE_THRESHOLD"] + pvUsagePercentageThreshold = Test_registry.instance.env["AZMON_ALERT_PV_USAGE_THRESHOLD"] if !pvUsagePercentageThreshold.nil? && !pvUsagePercentageThreshold.empty? pvUsagePercentageThresholdFloat = (pvUsagePercentageThreshold.to_f).round(2) metric_threshold_hash[Constants::PV_USED_BYTES] = pvUsagePercentageThresholdFloat end - jobCompletionTimeThreshold = ENV["AZMON_ALERT_JOB_COMPLETION_TIME_THRESHOLD"] + jobCompletionTimeThreshold = Test_registry.instance.env["AZMON_ALERT_JOB_COMPLETION_TIME_THRESHOLD"] if !jobCompletionTimeThreshold.nil? && !jobCompletionTimeThreshold.empty? jobCompletionTimeThresholdInt = jobCompletionTimeThreshold.to_i metric_threshold_hash[Constants::JOB_COMPLETION_TIME] = jobCompletionTimeThresholdInt diff --git a/source/plugins/ruby/constants.rb b/source/plugins/ruby/constants.rb index 40fa80c14..69da56488 100644 --- a/source/plugins/ruby/constants.rb +++ b/source/plugins/ruby/constants.rb @@ -129,5 +129,7 @@ class Constants ONEAGENT_FLUENT_SOCKET_NAME = "/var/run/mdsd/default_fluent.socket" #Tag prefix for output stream EXTENSION_OUTPUT_STREAM_ID_TAG_PREFIX = "dcr-" - + + LINUX_LOG_PATH = $in_unit_test.nil? ? "/var/opt/microsoft/docker-cimprov/log/" : "./" + WINDOWS_LOG_PATH = $in_unit_test.nil? ? "/etc/omsagentwindows/" : "./" end diff --git a/source/plugins/utils/extension.rb b/source/plugins/ruby/extension.rb similarity index 100% rename from source/plugins/utils/extension.rb rename to source/plugins/ruby/extension.rb diff --git a/source/plugins/utils/extension_utils.rb b/source/plugins/ruby/extension_utils.rb similarity index 100% rename from source/plugins/utils/extension_utils.rb rename to source/plugins/ruby/extension_utils.rb diff --git a/source/plugins/ruby/filter_cadvisor2mdm.rb b/source/plugins/ruby/filter_cadvisor2mdm.rb index 6bafa372a..902ce4bcf 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm.rb @@ -12,15 +12,18 @@ module Fluent::Plugin require_relative "kubelet_utils" require_relative "MdmMetricsGenerator" require_relative "in_kube_nodes" + require_relative "constants" + require_relative "test_registry" + require 'byebug' class CAdvisor2MdmFilter < Filter Fluent::Plugin.register_filter("cadvisor2mdm", self) config_param :enable_log, :integer, :default => 0 - config_param :log_path, :string, :default => "/var/opt/microsoft/docker-cimprov/log/filter_cadvisor2mdm.log" + config_param :log_path, :string, :default => Constants::LINUX_LOG_PATH + "filter_cadvisor2mdm.log" config_param :metrics_to_collect, :string, :default => "Constants::CPU_USAGE_NANO_CORES,Constants::MEMORY_WORKING_SET_BYTES,Constants::MEMORY_RSS_BYTES,Constants::PV_USED_BYTES" - @@hostName = (OMS::Common.get_hostname) + @@hostName = (OMS::Common.get_hostname) # TODO: mock this @process_incoming_stream = true @metrics_to_collect_hash = {} @@ -28,32 +31,37 @@ class CAdvisor2MdmFilter < Filter @@metric_threshold_hash = {} @@controller_type = "" - @@isWindows = false - @@os_type = ENV["OS_TYPE"] - if !@@os_type.nil? && !@@os_type.empty? && @@os_type.strip.casecmp("windows") == 0 - @@isWindows = true + def set_hostname (hostname) + @@hostname = hostname end def initialize super + + @@isWindows = false + @@os_type = Test_registry.instance.env["OS_TYPE"] + if !@@os_type.nil? && !@@os_type.empty? && @@os_type.strip.casecmp("windows") == 0 + @@isWindows = true + end end def configure(conf) super - @log = nil + @Log = nil if @enable_log - @log = Logger.new(@log_path, 1, 5000000) - @log.debug { "Starting filter_cadvisor2mdm plugin" } + @Log = Logger.new(@log_path, 1, 5000000) + @Log.debug { "Starting filter_cadvisor2mdm plugin" } end end def start + byebug super begin @process_incoming_stream = CustomMetricsUtils.check_custom_metrics_availability - @metrics_to_collect_hash = build_metrics_hash - @log.debug "After check_custom_metrics_availability process_incoming_stream #{@process_incoming_stream}" + @metrics_to_collect_hash = build_metrics_hash(@metrics_to_collect) + @Log.debug "After check_custom_metrics_availability process_incoming_stream #{@process_incoming_stream}" @@containerResourceUtilTelemetryTimeTracker = DateTime.now.to_time.to_i @@pvUsageTelemetryTimeTracker = DateTime.now.to_time.to_i @@ -78,15 +86,15 @@ def start @NodeCache = Fluent::Plugin::NodeStatsCache.new() end rescue => e - @log.info "Error initializing plugin #{e}" + @Log.info "Error initializing plugin #{e}" end end - def build_metrics_hash - @log.debug "Building Hash of Metrics to Collect" - metrics_to_collect_arr = @metrics_to_collect.split(",").map(&:strip) + def build_metrics_hash metrics_to_collect_list + @Log.debug "Building Hash of Metrics to Collect" + metrics_to_collect_arr = metrics_to_collect_list.split(",").map(&:strip) metrics_hash = metrics_to_collect_arr.map { |x| [x.downcase, true] }.to_h - @log.info "Metrics Collected : #{metrics_hash}" + @Log.info "Metrics Collected : #{metrics_hash}" return metrics_hash end @@ -106,8 +114,8 @@ def setThresholdExceededTelemetry(metricName) @pvExceededUsageThreshold = true end rescue => errorStr - @log.info "Error in setThresholdExceededTelemetry: #{errorStr}" - ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) + @Log.info "Error in setThresholdExceededTelemetry: #{errorStr}" + Test_registry.instance.applicationInsightsUtility.sendExceptionTelemetry(errorStr) end end @@ -125,15 +133,15 @@ def flushMetricTelemetry properties["CpuThresholdExceededInLastFlushInterval"] = @containersExceededCpuThreshold properties["MemRssThresholdExceededInLastFlushInterval"] = @containersExceededMemRssThreshold properties["MemWSetThresholdExceededInLastFlushInterval"] = @containersExceededMemWorkingSetThreshold - ApplicationInsightsUtility.sendCustomEvent(Constants::CONTAINER_RESOURCE_UTIL_HEART_BEAT_EVENT, properties) + Test_registry.instance.applicationInsightsUtility.sendCustomEvent(Constants::CONTAINER_RESOURCE_UTIL_HEART_BEAT_EVENT, properties) @containersExceededCpuThreshold = false @containersExceededMemRssThreshold = false @containersExceededMemWorkingSetThreshold = false @@containerResourceUtilTelemetryTimeTracker = DateTime.now.to_time.to_i end rescue => errorStr - @log.info "Error in flushMetricTelemetry: #{errorStr} for container resource util telemetry" - ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) + @Log.info "Error in flushMetricTelemetry: #{errorStr} for container resource util telemetry" + Test_registry.instance.applicationInsightsUtility.sendExceptionTelemetry(errorStr) end # Also send for PV usage metrics @@ -145,14 +153,14 @@ def flushMetricTelemetry pvProperties = {} pvProperties["PVUsageThresholdPercentage"] = @@metric_threshold_hash[Constants::PV_USED_BYTES] pvProperties["PVUsageThresholdExceededInLastFlushInterval"] = @pvExceededUsageThreshold - ApplicationInsightsUtility.sendCustomEvent(Constants::PV_USAGE_HEART_BEAT_EVENT, pvProperties) + Test_registry.instance.applicationInsightsUtility.sendCustomEvent(Constants::PV_USAGE_HEART_BEAT_EVENT, pvProperties) @pvExceededUsageThreshold = false @@pvUsageTelemetryTimeTracker = DateTime.now.to_time.to_i end end rescue => errorStr - @log.info "Error in flushMetricTelemetry: #{errorStr} for PV usage telemetry" - ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) + @Log.info "Error in flushMetricTelemetry: #{errorStr} for PV usage telemetry" + Test_registry.instance.applicationInsightsUtility.sendExceptionTelemetry(errorStr) end end @@ -184,7 +192,7 @@ def filter(tag, time, record) target_node_cpu_capacity_mc = @cpu_capacity target_node_cpu_allocatable_mc = @cpu_allocatable end - @log.info "Metric_value: #{metric_value} CPU Capacity #{target_node_cpu_capacity_mc} CPU Allocatable #{target_node_cpu_allocatable_mc} " + @Log.info "Metric_value: #{metric_value} CPU Capacity #{target_node_cpu_capacity_mc} CPU Allocatable #{target_node_cpu_allocatable_mc} " if target_node_cpu_capacity_mc != 0.0 percentage_metric_value = (metric_value) * 100 / target_node_cpu_capacity_mc end @@ -205,7 +213,7 @@ def filter(tag, time, record) target_node_mem_allocatable = @memory_allocatable # We do not need this value in the replicaset end - @log.info "Metric_value: #{metric_value} Memory Capacity #{target_node_mem_capacity} Memory Allocatable #{target_node_mem_allocatable}" + @Log.info "Metric_value: #{metric_value} Memory Capacity #{target_node_mem_capacity} Memory Allocatable #{target_node_mem_allocatable}" if target_node_mem_capacity != 0.0 percentage_metric_value = metric_value * 100 / target_node_mem_capacity end @@ -216,7 +224,7 @@ def filter(tag, time, record) allocatable_percentage_metric_value = 0.0 end end - @log.info "percentage_metric_value for metric: #{metric_name} for instance: #{record["Host"]} percentage: #{percentage_metric_value} allocatable_percentage: #{allocatable_percentage_metric_value}" + @Log.info "percentage_metric_value for metric: #{metric_name} for instance: #{record["Host"]} percentage: #{percentage_metric_value} allocatable_percentage: #{allocatable_percentage_metric_value}" # do some sanity checking. if percentage_metric_value > 100.0 @@ -224,14 +232,14 @@ def filter(tag, time, record) telemetryProperties["Computer"] = record["Host"] telemetryProperties["MetricName"] = metric_name telemetryProperties["MetricPercentageValue"] = percentage_metric_value - ApplicationInsightsUtility.sendCustomEvent("ErrorPercentageOutOfBounds", telemetryProperties) + Test_registry.instance.applicationInsightsUtility.sendCustomEvent("ErrorPercentageOutOfBounds", telemetryProperties) end if allocatable_percentage_metric_value > 100.0 telemetryProperties = {} telemetryProperties["Computer"] = record["Host"] telemetryProperties["MetricName"] = metric_name telemetryProperties["MetricAllocatablePercentageValue"] = allocatable_percentage_metric_value - ApplicationInsightsUtility.sendCustomEvent("ErrorPercentageOutOfBounds", telemetryProperties) + Test_registry.instance.applicationInsightsUtility.sendCustomEvent("ErrorPercentageOutOfBounds", telemetryProperties) end return MdmMetricsGenerator.getNodeResourceMetricRecords(record, metric_name, metric_value, percentage_metric_value, allocatable_percentage_metric_value) @@ -263,8 +271,8 @@ def filter(tag, time, record) end # Send this metric only if resource utilization is greater than configured threshold - @log.info "percentage_metric_value for metric: #{metricName} for instance: #{instanceName} percentage: #{percentage_metric_value}" - @log.info "@@metric_threshold_hash for #{metricName}: #{@@metric_threshold_hash[metricName]}" + @Log.info "percentage_metric_value for metric: #{metricName} for instance: #{instanceName} percentage: #{percentage_metric_value}" + @Log.info "@@metric_threshold_hash for #{metricName}: #{@@metric_threshold_hash[metricName]}" thresholdPercentage = @@metric_threshold_hash[metricName] # Flushing telemetry here since, we return as soon as we generate the metric @@ -286,8 +294,8 @@ def filter(tag, time, record) return [] end #end if block for process incoming stream check rescue Exception => e - @log.info "Error processing cadvisor record Exception: #{e.class} Message: #{e.message}" - ApplicationInsightsUtility.sendExceptionTelemetry(e.backtrace) + @Log.info "Error processing cadvisor record Exception: #{e.class} Message: #{e.message}" + Test_registry.instance.applicationInsightsUtility.sendExceptionTelemetry(e.backtrace) return [] #return empty array if we ran into any errors end end @@ -302,8 +310,8 @@ def filterPVInsightsMetrics(record) if capacity != 0 percentage_metric_value = (usage * 100.0) / capacity end - @log.info "percentage_metric_value for metric: #{metricName} percentage: #{percentage_metric_value}" - @log.info "@@metric_threshold_hash for #{metricName}: #{@@metric_threshold_hash[metricName]}" + @Log.info "percentage_metric_value for metric: #{metricName} percentage: #{percentage_metric_value}" + @Log.info "@@metric_threshold_hash for #{metricName}: #{@@metric_threshold_hash[metricName]}" computer = record["Computer"] resourceDimensions = record["Tags"] @@ -324,60 +332,61 @@ def filterPVInsightsMetrics(record) end # end if block for dataItem name check return [] rescue Exception => e - @log.info "Error processing cadvisor insights metrics record Exception: #{e.class} Message: #{e.message}" - ApplicationInsightsUtility.sendExceptionTelemetry(e.backtrace) + @Log.info "Error processing cadvisor insights metrics record Exception: #{e.class} Message: #{e.message}" + Test_registry.instance.applicationInsightsUtility.sendExceptionTelemetry(e.backtrace) return [] #return empty array if we ran into any errors end end def ensure_cpu_memory_capacity_and_allocatable_set - @@controller_type = ENV["CONTROLLER_TYPE"] + @@controller_type = Test_registry.instance.env["CONTROLLER_TYPE"] if @cpu_capacity != 0.0 && @memory_capacity != 0.0 && @@controller_type.downcase == "replicaset" - @log.info "CPU And Memory Capacity are already set and their values are as follows @cpu_capacity : #{@cpu_capacity}, @memory_capacity: #{@memory_capacity}" + @Log.info "CPU And Memory Capacity are already set and their values are as follows @cpu_capacity : #{@cpu_capacity}, @memory_capacity: #{@memory_capacity}" return end if @@controller_type.downcase == "daemonset" && @cpu_capacity != 0.0 && @memory_capacity != 0.0 && @cpu_allocatable != 0.0 && @memory_allocatable != 0.0 - @log.info "CPU And Memory Capacity are already set and their values are as follows @cpu_capacity : #{@cpu_capacity}, @memory_capacity: #{@memory_capacity}" - @log.info "CPU And Memory Allocatable are already set and their values are as follows @cpu_allocatable : #{@cpu_allocatable}, @memory_allocatable: #{@memory_allocatable}" + @Log.info "CPU And Memory Capacity are already set and their values are as follows @cpu_capacity : #{@cpu_capacity}, @memory_capacity: #{@memory_capacity}" + @Log.info "CPU And Memory Allocatable are already set and their values are as follows @cpu_allocatable : #{@cpu_allocatable}, @memory_allocatable: #{@memory_allocatable}" return end if @@controller_type.downcase == "replicaset" - @log.info "ensure_cpu_memory_capacity_set @cpu_capacity #{@cpu_capacity} @memory_capacity #{@memory_capacity}" + @Log.info "ensure_cpu_memory_capacity_set @cpu_capacity #{@cpu_capacity} @memory_capacity #{@memory_capacity}" begin - resourceUri = KubernetesApiClient.getNodesResourceUri("nodes?fieldSelector=metadata.name%3D#{@@hostName}") - nodeInventory = JSON.parse(KubernetesApiClient.getKubeResourceInfo(resourceUri).body) + byebug + resourceUri = Test_registry.instance.kubernetesApiClient.getNodesResourceUri("nodes?fieldSelector=metadata.name%3D#{@@hostName}") + nodeInventory = JSON.parse(Test_registry.instance.kubernetesApiClient.getKubeResourceInfo(resourceUri).body) rescue Exception => e - @log.info "Error when getting nodeInventory from kube API. Exception: #{e.class} Message: #{e.message} " - ApplicationInsightsUtility.sendExceptionTelemetry(e.backtrace) + @Log.info "Error when getting nodeInventory from kube API. Exception: #{e.class} Message: #{e.message} " + Test_registry.instance.applicationInsightsUtility.sendExceptionTelemetry(e.backtrace) end if !nodeInventory.nil? - cpu_capacity_json = KubernetesApiClient.parseNodeLimits(nodeInventory, "capacity", "cpu", "cpuCapacityNanoCores") + cpu_capacity_json = Test_registry.instance.kubernetesApiClient.parseNodeLimits(nodeInventory, "capacity", "cpu", "cpuCapacityNanoCores") if !cpu_capacity_json.nil? metricVal = JSON.parse(cpu_capacity_json[0]["json_Collections"])[0]["Value"] if !metricVal.to_s.nil? @cpu_capacity = metricVal - @log.info "CPU Limit #{@cpu_capacity}" + @Log.info "CPU Limit #{@cpu_capacity}" end else - @log.info "Error getting cpu_capacity" + @Log.info "Error getting cpu_capacity" end - memory_capacity_json = KubernetesApiClient.parseNodeLimits(nodeInventory, "capacity", "memory", "memoryCapacityBytes") + memory_capacity_json = Test_registry.instance.kubernetesApiClient.parseNodeLimits(nodeInventory, "capacity", "memory", "memoryCapacityBytes") if !memory_capacity_json.nil? metricVal = JSON.parse(cpu_capacity_json[0]["json_Collections"])[0]["Value"] if !metricVal.to_s.nil? @memory_capacity = metricVal - @log.info "Memory Limit #{@memory_capacity}" + @Log.info "Memory Limit #{@memory_capacity}" end else - @log.info "Error getting memory_capacity" + @Log.info "Error getting memory_capacity" end end elsif @@controller_type.downcase == "daemonset" - capacity_from_kubelet = KubeletUtils.get_node_capacity + capacity_from_kubelet = Test_registry.instance.kubeletUtils.get_node_capacity # Error handling in case /metrics/cadvsior endpoint fails if !capacity_from_kubelet.nil? && capacity_from_kubelet.length > 1 @@ -385,10 +394,10 @@ def ensure_cpu_memory_capacity_and_allocatable_set @memory_capacity = capacity_from_kubelet[1] else # cpu_capacity and memory_capacity keep initialized value of 0.0 - @log.error "Error getting capacity_from_kubelet: cpu_capacity and memory_capacity" + @Log.error "Error getting capacity_from_kubelet: cpu_capacity and memory_capacity" end - allocatable_from_kubelet = KubeletUtils.get_node_allocatable(@cpu_capacity, @memory_capacity) + allocatable_from_kubelet = Test_registry.instance.kubeletUtils.get_node_allocatable(@cpu_capacity, @memory_capacity) # Error handling in case /configz endpoint fails if !allocatable_from_kubelet.nil? && allocatable_from_kubelet.length > 1 @@ -396,18 +405,19 @@ def ensure_cpu_memory_capacity_and_allocatable_set @memory_allocatable = allocatable_from_kubelet[1] else # cpu_allocatable and memory_allocatable keep initialized value of 0.0 - @log.error "Error getting allocatable_from_kubelet: cpu_allocatable and memory_allocatable" + @Log.error "Error getting allocatable_from_kubelet: cpu_allocatable and memory_allocatable" end end end def filter_stream(tag, es) + byebug new_es = Fluent::MultiEventStream.new begin ensure_cpu_memory_capacity_and_allocatable_set # Getting container limits hash if @process_incoming_stream - @containerCpuLimitHash, @containerMemoryLimitHash, @containerResourceDimensionHash = KubeletUtils.get_all_container_limits + @containerCpuLimitHash, @containerMemoryLimitHash, @containerResourceDimensionHash = KubeletUtils.get_all_container_limits # TODO: mock this end es.each { |time, record| @@ -417,7 +427,7 @@ def filter_stream(tag, es) } if filtered_records } rescue => e - @log.info "Error in filter_stream #{e.message}" + @Log.info "Error in filter_stream #{e.message}" end new_es end diff --git a/source/plugins/ruby/filter_cadvisor2mdm_test.rb b/source/plugins/ruby/filter_cadvisor2mdm_test.rb new file mode 100644 index 000000000..b5b531c27 --- /dev/null +++ b/source/plugins/ruby/filter_cadvisor2mdm_test.rb @@ -0,0 +1,115 @@ +$in_unit_test = true + +require "test-unit" +require 'fluent/test' +require 'fluent/test/driver/filter' +require 'fluent/test/helpers' +require_relative 'filter_cadvisor2mdm.rb' +require_relative 'test_registry' +require_relative 'KubernetesApiClient' +require 'byebug' + + +class MyInputTest < Test::Unit::TestCase + include Fluent::Test::Helpers + + setup do + Fluent::Test.setup + end + + def create_driver(conf = "") + Fluent::Test::Driver::Filter.new(Fluent::Plugin::CAdvisor2MdmFilter).configure(conf) + end + + test 'filter' do + + class Ai_utility_stub + class << self + def sendCustomEvent(a, b) + end + + def sendExceptionTelemetry (errorstr) + # this shouldn't happen, why was there an exception? + byebug + end + end + end + + class KubernetesApiClientMock < KubernetesApiClient + class GetNodesResponse + def body + return "{\"kind\":\"NodeList\",\"apiVersion\":\"v1\",\"metadata\":{\"selfLink\":\"/api/v1/nodes\",\"resourceVersion\":\"4597672\"},\"items\":[{\"metadata\":{\"name\":\"aks-nodepool1-24816391-vmss000000\",\"selfLink\":\"/api/v1/nodes/aks-nodepool1-24816391-vmss000000\",\"uid\":\"fe073f0a-e6bf-4d68-b4e5-ffaa42b91528\",\"resourceVersion\":\"4597521\",\"creationTimestamp\":\"2021-07-21T23:40:14Z\",\"labels\":{\"agentpool\":\"nodepool1\",\"beta.kubernetes.io/arch\":\"amd64\",\"beta.kubernetes.io/instance-type\":\"Standard_DS2_v2\",\"beta.kubernetes.io/os\":\"linux\",\"failure-domain.beta.kubernetes.io/region\":\"westus2\",\"failure-domain.beta.kubernetes.io/zone\":\"0\",\"kubernetes.azure.com/cluster\":\"MC_davidaks16_davidaks16_westus2\",\"kubernetes.azure.com/mode\":\"system\",\"kubernetes.azure.com/node-image-version\":\"AKSUbuntu-1804gen2containerd-2021.07.03\",\"kubernetes.azure.com/os-sku\":\"Ubuntu\",\"kubernetes.azure.com/role\":\"agent\",\"kubernetes.io/arch\":\"amd64\",\"kubernetes.io/hostname\":\"aks-nodepool1-24816391-vmss000000\",\"kubernetes.io/os\":\"linux\",\"kubernetes.io/role\":\"agent\",\"node-role.kubernetes.io/agent\":\"\",\"node.kubernetes.io/instance-type\":\"Standard_DS2_v2\",\"storageprofile\":\"managed\",\"storagetier\":\"Premium_LRS\",\"topology.kubernetes.io/region\":\"westus2\",\"topology.kubernetes.io/zone\":\"0\"},\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"0\",\"volumes.kubernetes.io/controller-managed-attach-detach\":\"true\"},\"managedFields\":[{\"manager\":\"kube-controller-manager\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-07-21T23:40:20Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:metadata\":{\"f:annotations\":{\"f:node.alpha.kubernetes.io/ttl\":{}}}}},{\"manager\":\"kubelet\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-07-21T23:40:24Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:metadata\":{\"f:annotations\":{\".\":{},\"f:volumes.kubernetes.io/controller-managed-attach-detach\":{}},\"f:labels\":{\".\":{},\"f:agentpool\":{},\"f:beta.kubernetes.io/arch\":{},\"f:beta.kubernetes.io/instance-type\":{},\"f:beta.kubernetes.io/os\":{},\"f:failure-domain.beta.kubernetes.io/region\":{},\"f:failure-domain.beta.kubernetes.io/zone\":{},\"f:kubernetes.azure.com/cluster\":{},\"f:kubernetes.azure.com/mode\":{},\"f:kubernetes.azure.com/node-image-version\":{},\"f:kubernetes.azure.com/os-sku\":{},\"f:kubernetes.azure.com/role\":{},\"f:kubernetes.io/arch\":{},\"f:kubernetes.io/hostname\":{},\"f:kubernetes.io/os\":{},\"f:node.kubernetes.io/instance-type\":{},\"f:storageprofile\":{},\"f:storagetier\":{},\"f:topology.kubernetes.io/region\":{},\"f:topology.kubernetes.io/zone\":{}}},\"f:spec\":{\"f:providerID\":{}},\"f:status\":{\"f:addresses\":{\".\":{},\"k:{\\\"type\\\":\\\"Hostname\\\"}\":{\".\":{},\"f:address\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"InternalIP\\\"}\":{\".\":{},\"f:address\":{},\"f:type\":{}}},\"f:allocatable\":{\".\":{},\"f:attachable-volumes-azure-disk\":{},\"f:cpu\":{},\"f:ephemeral-storage\":{},\"f:hugepages-1Gi\":{},\"f:hugepages-2Mi\":{},\"f:memory\":{},\"f:pods\":{}},\"f:capacity\":{\".\":{},\"f:attachable-volumes-azure-disk\":{},\"f:cpu\":{},\"f:ephemeral-storage\":{},\"f:hugepages-1Gi\":{},\"f:hugepages-2Mi\":{},\"f:memory\":{},\"f:pods\":{}},\"f:conditions\":{\".\":{},\"k:{\\\"type\\\":\\\"DiskPressure\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"MemoryPressure\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"PIDPressure\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"Ready\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}}},\"f:config\":{},\"f:daemonEndpoints\":{\"f:kubeletEndpoint\":{\"f:Port\":{}}},\"f:images\":{},\"f:nodeInfo\":{\"f:architecture\":{},\"f:bootID\":{},\"f:containerRuntimeVersion\":{},\"f:kernelVersion\":{},\"f:kubeProxyVersion\":{},\"f:kubeletVersion\":{},\"f:machineID\":{},\"f:operatingSystem\":{},\"f:osImage\":{},\"f:systemUUID\":{}}}}},{\"manager\":\"kubectl-label\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-07-21T23:40:53Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:metadata\":{\"f:labels\":{\"f:kubernetes.io/role\":{},\"f:node-role.kubernetes.io/agent\":{}}}}},{\"manager\":\"node-problem-detector\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-08-10T18:10:02Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:status\":{\"f:conditions\":{\"k:{\\\"type\\\":\\\"ContainerRuntimeProblem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FilesystemCorruptionProblem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FreezeScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentContainerdRestart\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentDockerRestart\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentKubeletRestart\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentUnregisterNetDevice\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"KernelDeadlock\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"KubeletProblem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"PreemptScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"ReadonlyFilesystem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"RebootScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"RedeployScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"TerminateScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}}}}}}]},\"spec\":{\"providerID\":\"azure:///subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/mc_davidaks16_davidaks16_westus2/providers/Microsoft.Compute/virtualMachineScaleSets/aks-nodepool1-24816391-vmss/virtualMachines/0\"},\"status\":{\"capacity\":{\"attachable-volumes-azure-disk\":\"8\",\"cpu\":\"2\",\"ephemeral-storage\":\"129900528Ki\",\"hugepages-1Gi\":\"0\",\"hugepages-2Mi\":\"0\",\"memory\":\"7120616Ki\",\"pods\":\"30\"},\"allocatable\":{\"attachable-volumes-azure-disk\":\"8\",\"cpu\":\"1900m\",\"ephemeral-storage\":\"119716326407\",\"hugepages-1Gi\":\"0\",\"hugepages-2Mi\":\"0\",\"memory\":\"4675304Ki\",\"pods\":\"30\"},\"conditions\":[{\"type\":\"FrequentContainerdRestart\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentContainerdRestart\",\"message\":\"containerd is functioning properly\"},{\"type\":\"FreezeScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFreezeScheduled\",\"message\":\"VM has no scheduled Freeze event\"},{\"type\":\"FrequentDockerRestart\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentDockerRestart\",\"message\":\"docker is functioning properly\"},{\"type\":\"FilesystemCorruptionProblem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"FilesystemIsOK\",\"message\":\"Filesystem is healthy\"},{\"type\":\"KernelDeadlock\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"KernelHasNoDeadlock\",\"message\":\"kernel has no deadlock\"},{\"type\":\"TerminateScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoTerminateScheduled\",\"message\":\"VM has no scheduled Terminate event\"},{\"type\":\"ReadonlyFilesystem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"FilesystemIsNotReadOnly\",\"message\":\"Filesystem is not read-only\"},{\"type\":\"FrequentUnregisterNetDevice\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentUnregisterNetDevice\",\"message\":\"node is functioning properly\"},{\"type\":\"KubeletProblem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"KubeletIsUp\",\"message\":\"kubelet service is up\"},{\"type\":\"PreemptScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:11:11Z\",\"reason\":\"NoPreemptScheduled\",\"message\":\"VM has no scheduled Preempt event\"},{\"type\":\"RedeployScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoRedeployScheduled\",\"message\":\"VM has no scheduled Redeploy event\"},{\"type\":\"ContainerRuntimeProblem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"ContainerRuntimeIsUp\",\"message\":\"container runtime service is up\"},{\"type\":\"FrequentKubeletRestart\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentKubeletRestart\",\"message\":\"kubelet is functioning properly\"},{\"type\":\"RebootScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoRebootScheduled\",\"message\":\"VM has no scheduled Reboot event\"},{\"type\":\"MemoryPressure\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:14Z\",\"reason\":\"KubeletHasSufficientMemory\",\"message\":\"kubelet has sufficient memory available\"},{\"type\":\"DiskPressure\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:14Z\",\"reason\":\"KubeletHasNoDiskPressure\",\"message\":\"kubelet has no disk pressure\"},{\"type\":\"PIDPressure\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:14Z\",\"reason\":\"KubeletHasSufficientPID\",\"message\":\"kubelet has sufficient PID available\"},{\"type\":\"Ready\",\"status\":\"True\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:24Z\",\"reason\":\"KubeletReady\",\"message\":\"kubelet is posting ready status. AppArmor enabled\"}],\"addresses\":[{\"type\":\"Hostname\",\"address\":\"aks-nodepool1-24816391-vmss000000\"},{\"type\":\"InternalIP\",\"address\":\"10.240.0.4\"}],\"daemonEndpoints\":{\"kubeletEndpoint\":{\"Port\":10250}},\"nodeInfo\":{\"machineID\":\"17a654260e2c4a9bb3a3eb4b4188e4b4\",\"systemUUID\":\"7ff599e4-909e-4950-a044-ff8613af3af9\",\"bootID\":\"02bb865b-a469-43cd-8b0b-5ceb4ecd80b0\",\"kernelVersion\":\"5.4.0-1051-azure\",\"osImage\":\"Ubuntu 18.04.5 LTS\",\"containerRuntimeVersion\":\"containerd://1.4.4+azure\",\"kubeletVersion\":\"v1.19.11\",\"kubeProxyVersion\":\"v1.19.11\",\"operatingSystem\":\"linux\",\"architecture\":\"amd64\"},\"images\":[{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021-1\"],\"sizeBytes\":331689060},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021\"],\"sizeBytes\":330099815},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021-hotfix\"],\"sizeBytes\":271471426},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021\"],\"sizeBytes\":269703297},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod03262021\"],\"sizeBytes\":264732875},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.19.0\"],\"sizeBytes\":166352383},{\"names\":[\"mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210623.2\"],\"sizeBytes\":147750148},{\"names\":[\"mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210524.1\"],\"sizeBytes\":146446618},{\"names\":[\"mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210427.1\"],\"sizeBytes\":136242776},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.8.9.5\"],\"sizeBytes\":101794833},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.47.0\"],\"sizeBytes\":101445696},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/autoscaler/cluster-proportional-autoscaler:1.3.0_v0.0.5\"],\"sizeBytes\":101194562},{\"names\":[\"mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210623.2\"],\"sizeBytes\":96125176},{\"names\":[\"mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210524.1\"],\"sizeBytes\":95879501},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/exechealthz:1.2_v0.0.5\"],\"sizeBytes\":94348102},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.8.9.2\"],\"sizeBytes\":93537927},{\"names\":[\"mcr.microsoft.com/aks/acc/sgx-attestation:2.0\"],\"sizeBytes\":91841669},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.4.0\"],\"sizeBytes\":91324193},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.2.0\"],\"sizeBytes\":89103171},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.0.1-rc3\"],\"sizeBytes\":86839805},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.2.0\"],\"sizeBytes\":86488586},{\"names\":[\"mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210427.1\"],\"sizeBytes\":86120048},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.3.0\"],\"sizeBytes\":81252495},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.4.0\"],\"sizeBytes\":79586703},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.4.0\"],\"sizeBytes\":78795016},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.2.0\"],\"sizeBytes\":76527179},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.1.8\"],\"sizeBytes\":75025803},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.2.2_hotfix\"],\"sizeBytes\":73533889},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.3.1\"],\"sizeBytes\":72242894},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.2.8\"],\"sizeBytes\":70622822},{\"names\":[\"mcr.microsoft.com/oss/nvidia/k8s-device-plugin:v0.9.0\"],\"sizeBytes\":67291599},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.1\"],\"sizeBytes\":66415836},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc7\"],\"sizeBytes\":65965658},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.2.1\"],\"sizeBytes\":64123775},{\"names\":[\"mcr.microsoft.com/oss/calico/cni:v3.8.9.3\"],\"sizeBytes\":63581323},{\"names\":[\"mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8\"],\"sizeBytes\":63154716},{\"names\":[\"mcr.microsoft.com/oss/calico/cni:v3.8.9.2\"],\"sizeBytes\":61626312},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.18.1\"],\"sizeBytes\":60500885},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.17.2\"],\"sizeBytes\":58419768},{\"names\":[\"mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8_hotfix\",\"mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8post2\"],\"sizeBytes\":56368756},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:282543237a1aa3f407656290f454b7068a92e1abe2156082c750d5abfbcad90c\",\"mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.2\"],\"sizeBytes\":56310724},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.19.0\"],\"sizeBytes\":55228749},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.1\"],\"sizeBytes\":54692048},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc3\"],\"sizeBytes\":50803639},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.19\"],\"sizeBytes\":49759361},{\"names\":[\"mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.5\"],\"sizeBytes\":49704644},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.21\"],\"sizeBytes\":49372390},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:a64d3538b72905b07356881314755b02db3675ff47ee2bcc49dd7be856e285d5\",\"mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526\"],\"sizeBytes\":49322942},{\"names\":[\"mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.4\"],\"sizeBytes\":48108311},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kubernetes-dashboard:v1.10.1\"],\"sizeBytes\":44907744}],\"config\":{}}}]}\n" + end + end + class << self + def getKubeResourceInfo(resource, api_group: nil) + if resource == "nodes?fieldSelector=metadata.name%3DWIN-T14B9CT7KMS" + return GetNodesResponse.new() + end + # this means that a saved input is missing + byebug + end + end + end + + Test_registry.instance.env = {"CONTROLLER_TYPE" => "ReplicaSet", + "OS_TYPE" => "linux", + "AZMON_ALERT_CONTAINER_CPU_THRESHOLD" => Constants::DEFAULT_MDM_CPU_UTILIZATION_THRESHOLD.to_s, + "AZMON_ALERT_CONTAINER_MEMORY_RSS_THRESHOLD" => Constants::DEFAULT_MDM_MEMORY_RSS_THRESHOLD.to_s, + "AZMON_ALERT_CONTAINER_MEMORY_WORKING_SET_THRESHOLD" => Constants::DEFAULT_MDM_MEMORY_WORKING_SET_THRESHOLD.to_s, + "AZMON_ALERT_PV_USAGE_THRESHOLD" => Constants::DEFAULT_MDM_PV_UTILIZATION_THRESHOLD.to_s, + "AZMON_ALERT_JOB_COMPLETION_TIME_THRESHOLD" => Constants::DEFAULT_MDM_JOB_COMPLETED_TIME_THRESHOLD_MINUTES.to_s, + "AKS_REGION" => "westus2", + "AKS_RESOURCE_ID" => "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/rg/providers/Microsoft.ContainerService/managedClusters/clustername", + "CLOUD_ENVIRONMENT" => "azurepubliccloud"} # TODO: this is actually set to public in running containers. Figure out how @process_incoming_stream resolves to true + Test_registry.instance.applicationInsightsUtility = Ai_utility_stub.new() + Test_registry.instance.kubernetesApiClient = KubernetesApiClientMock + + config = %[ + metrics_to_collect cpuUsageNanoCores,memoryWorkingSetBytes,pvUsedBytes + @log_level info + ] + + data = [ + {"tag" => "mdm.cadvisorperf", "time" => 1628198199.2757478, "data" => {"DataItems"=>[{"Timestamp"=>"2021-08-05T21:16:39Z", "Host"=>"akswin00000c", "ObjectName"=>"K8SContainer", "InstanceName"=>"/subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/davidwin6/providers/Microsoft.ContainerService/managedClusters/davidwin6/9bb73e59-9034-474a-92ab-5e028f18dbe9/omsagent-win", "Collections"=>[{"CounterName"=>"memoryWorkingSetBytes", "Value"=>272093184}]}], "DataType"=>"LINUX_PERF_BLOB", "IPName"=>"LogManagement"}} + ] + + expected_output = [ + {"tag" => "mdm.cadvisorperf", "time" => 1628198199.2757478, "data" => {"DataItems"=>[{"Timestamp"=>"2021-08-05T21:16:39Z", "Host"=>"akswin00000c", "ObjectName"=>"K8SContainer", "InstanceName"=>"/subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/davidwin6/providers/Microsoft.ContainerService/managedClusters/davidwin6/9bb73e59-9034-474a-92ab-5e028f18dbe9/omsagent-win", "Collections"=>[{"CounterName"=>"memoryWorkingSetBytes", "Value"=>272093184}]}], "DataType"=>"LINUX_PERF_BLOB", "IPName"=>"LogManagement"}} + ] + + d = create_driver(config) + d.instance.set_hostname("aks-nodepool1-24816391-vmss000000") + d.instance.start # TODO: why doesn't the fluentd test harness do this automatically? + time = event_time + + d.run do + d.feed(data[0]["tag"], time, data[0]["data"]) + end + + puts d.filtered_records.size + puts d.filtered_records + + assert_equal(0, d.filtered_records.size) + end + + + + test "build_metrics_hash" do + + instance = create_driver.instance + + expected = {"constants::cpu_usage_nano_cores" => true, "constants::memory_working_set_bytes" => true, "constants::memory_rss_bytes"=> true, "constants::pv_used_bytes"=> true} + actual = instance.build_metrics_hash "Constants::CPU_USAGE_NANO_CORES,Constants::MEMORY_WORKING_SET_BYTES,Constants::MEMORY_RSS_BYTES,Constants::PV_USED_BYTES" + assert_equal(expected, actual) + + assert_equal({}, instance.build_metrics_hash("")) + + assert_equal({"foobar" => true}, instance.build_metrics_hash("foobar")) + + end + + + + +end \ No newline at end of file diff --git a/source/plugins/ruby/kubelet_utils.rb b/source/plugins/ruby/kubelet_utils.rb index e31407b54..f5ee1e57c 100644 --- a/source/plugins/ruby/kubelet_utils.rb +++ b/source/plugins/ruby/kubelet_utils.rb @@ -11,9 +11,9 @@ class KubeletUtils @os_type = ENV["OS_TYPE"] if !@os_type.nil? && !@os_type.empty? && @os_type.strip.casecmp("windows") == 0 - @log_path = "/etc/omsagentwindows/filter_cadvisor2mdm.log" + @log_path = Constants::WINDOWS_LOG_PATH + "filter_cadvisor2mdm.log" else - @log_path = "/var/opt/microsoft/docker-cimprov/log/filter_cadvisor2mdm.log" + @log_path = Constants::LINUX_LOG_PATH + "filter_cadvisor2mdm.log" end @log = Logger.new(@log_path, 1, 5000000) diff --git a/source/plugins/ruby/mdm_metrics_generator.log b/source/plugins/ruby/mdm_metrics_generator.log new file mode 100644 index 000000000..d0d109899 --- /dev/null +++ b/source/plugins/ruby/mdm_metrics_generator.log @@ -0,0 +1 @@ +# Logfile created on 2021-08-04 17:54:56 -0700 by logger.rb/61378 diff --git a/source/plugins/utils/oms_common.rb b/source/plugins/ruby/oms_common.rb similarity index 100% rename from source/plugins/utils/oms_common.rb rename to source/plugins/ruby/oms_common.rb diff --git a/source/plugins/utils/omslog.rb b/source/plugins/ruby/omslog.rb similarity index 100% rename from source/plugins/utils/omslog.rb rename to source/plugins/ruby/omslog.rb diff --git a/source/plugins/ruby/test_registry.rb b/source/plugins/ruby/test_registry.rb new file mode 100644 index 000000000..b27d4db35 --- /dev/null +++ b/source/plugins/ruby/test_registry.rb @@ -0,0 +1,16 @@ +# require_relative 'KubernetesApiClient' +require_relative 'ApplicationInsightsUtility' + + +class Test_registry + include Singleton + + attr_reader :applicationInsightsUtility, :env, :kubernetesApiClient + attr_writer :applicationInsightsUtility, :env, :kubernetesApiClient + + def initialize + @applicationInsightsUtility = ApplicationInsightsUtility + @env = ENV + @kubernetesApiClient = KubernetesApiClient + end +end diff --git a/test/unit-tests/run_go_tests.sh b/test/unit-tests/run_go_tests.sh new file mode 100755 index 000000000..acc492e62 --- /dev/null +++ b/test/unit-tests/run_go_tests.sh @@ -0,0 +1,5 @@ + +cd ../../source/plugins/go/src +go test . +cd - + diff --git a/test/unit-tests/run_ruby_tests.sh b/test/unit-tests/run_ruby_tests.sh new file mode 100644 index 000000000..db3c3e81c --- /dev/null +++ b/test/unit-tests/run_ruby_tests.sh @@ -0,0 +1,5 @@ + +cd ../../source/plugins/ruby + +cd - + From 564bb5f4dbc648c174e05762b00ccac25bcaeb31 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Wed, 11 Aug 2021 14:32:52 -0700 Subject: [PATCH 08/33] added some comments --- .../plugins/ruby/filter_cadvisor2mdm_test.rb | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/source/plugins/ruby/filter_cadvisor2mdm_test.rb b/source/plugins/ruby/filter_cadvisor2mdm_test.rb index b5b531c27..421fd4cb1 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm_test.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm_test.rb @@ -21,6 +21,23 @@ def create_driver(conf = "") Fluent::Test::Driver::Filter.new(Fluent::Plugin::CAdvisor2MdmFilter).configure(conf) end + # A relatively simple test for a helper method + test "build_metrics_hash" do + + instance = create_driver.instance + + expected = {"constants::cpu_usage_nano_cores" => true, "constants::memory_working_set_bytes" => true, "constants::memory_rss_bytes"=> true, "constants::pv_used_bytes"=> true} + actual = instance.build_metrics_hash "Constants::CPU_USAGE_NANO_CORES,Constants::MEMORY_WORKING_SET_BYTES,Constants::MEMORY_RSS_BYTES,Constants::PV_USED_BYTES" + assert_equal(expected, actual) + + assert_equal({}, instance.build_metrics_hash("")) + + assert_equal({"foobar" => true}, instance.build_metrics_hash("foobar")) + + end + + + # a much more complicated test for the filter method of filter_cadvisor2mdm (this is an allup test) test 'filter' do class Ai_utility_stub @@ -93,23 +110,4 @@ def getKubeResourceInfo(resource, api_group: nil) assert_equal(0, d.filtered_records.size) end - - - test "build_metrics_hash" do - - instance = create_driver.instance - - expected = {"constants::cpu_usage_nano_cores" => true, "constants::memory_working_set_bytes" => true, "constants::memory_rss_bytes"=> true, "constants::pv_used_bytes"=> true} - actual = instance.build_metrics_hash "Constants::CPU_USAGE_NANO_CORES,Constants::MEMORY_WORKING_SET_BYTES,Constants::MEMORY_RSS_BYTES,Constants::PV_USED_BYTES" - assert_equal(expected, actual) - - assert_equal({}, instance.build_metrics_hash("")) - - assert_equal({"foobar" => true}, instance.build_metrics_hash("foobar")) - - end - - - - end \ No newline at end of file From 565bbb1ee6b7ba5469f0eb0f1c66ec2e253c3171 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Wed, 11 Aug 2021 20:19:44 -0700 Subject: [PATCH 09/33] testing github actions --- .github/workflows/run_unit_tests.yml | 45 +++++++++++++++ source/plugins/ruby/CustomMetricsUtils.rb | 10 ++-- source/plugins/ruby/KubernetesApiClient.rb | 4 +- source/plugins/ruby/filter_cadvisor2mdm.rb | 56 ++++++++++--------- .../plugins/ruby/filter_cadvisor2mdm_test.rb | 14 ++--- test/unit-tests/run_ruby_tests.sh | 2 +- 6 files changed, 89 insertions(+), 42 deletions(-) create mode 100644 .github/workflows/run_unit_tests.yml diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml new file mode 100644 index 000000000..eee621602 --- /dev/null +++ b/.github/workflows/run_unit_tests.yml @@ -0,0 +1,45 @@ +name: Run Unit Tests +on: [opened, synchronize, reopened] +jobs: + Actions-Demo: + runs-on: ubuntu-latest + steps: + - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." + - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!" + - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}." + - name: Check out repository code + uses: actions/checkout@v2 + - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." + - run: echo "🖥️ The workflow is now ready to test your code on the runner." + - name: List files in the repository + run: | + ls ${{ github.workspace }} + - run: echo "🍏 This job's status is ${{ job.status }}." + Golang-Tests: + runs-on: ubuntu-latest + steps: + - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." + - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!" + - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}." + - name: Check out repository code + uses: actions/checkout@v2 + - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." + - name: List files in the repository + run: | + cd Docker-Provider + ./test/unit-tests/run_go_tests.sh + - run: echo "🍏 This job's status is ${{ job.status }}." + Ruby-Tests: + runs-on: ubuntu-latest + steps: + - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." + - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!" + - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}." + - name: Check out repository code + uses: actions/checkout@v2 + - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." + - run: echo "🖥️ The workflow is now ready to test your code on the runner." + - name: List files in the repository + run: | + ls ${{ github.workspace }} + - run: echo "🍏 This job's status is ${{ job.status }}." \ No newline at end of file diff --git a/source/plugins/ruby/CustomMetricsUtils.rb b/source/plugins/ruby/CustomMetricsUtils.rb index 63172e05a..14c3c8b72 100644 --- a/source/plugins/ruby/CustomMetricsUtils.rb +++ b/source/plugins/ruby/CustomMetricsUtils.rb @@ -1,17 +1,15 @@ #!/usr/local/bin/ruby # frozen_string_literal: true -require_relative "test_registry" - class CustomMetricsUtils def initialize end class << self - def check_custom_metrics_availability - aks_region = Test_registry.instance.env['AKS_REGION'] - aks_resource_id = Test_registry.instance.env['AKS_RESOURCE_ID'] - aks_cloud_environment = Test_registry.instance.env['CLOUD_ENVIRONMENT'] + def check_custom_metrics_availability(env=ENV) + aks_region = env['AKS_REGION'] + aks_resource_id = env['AKS_RESOURCE_ID'] + aks_cloud_environment = env['CLOUD_ENVIRONMENT'] if aks_region.to_s.empty? || aks_resource_id.to_s.empty? return false # This will also take care of AKS-Engine Scenario. AKS_REGION/AKS_RESOURCE_ID is not set for AKS-Engine. Only ACS_RESOURCE_NAME is set end diff --git a/source/plugins/ruby/KubernetesApiClient.rb b/source/plugins/ruby/KubernetesApiClient.rb index 3187f4a32..e118aa320 100644 --- a/source/plugins/ruby/KubernetesApiClient.rb +++ b/source/plugins/ruby/KubernetesApiClient.rb @@ -12,8 +12,6 @@ class KubernetesApiClient require_relative "oms_common" require_relative "constants" - require_relative "test_registry" - @@ApiVersion = "v1" @@ApiVersionApps = "v1" @@ApiGroupApps = "apps" @@ -27,6 +25,8 @@ class KubernetesApiClient #@@IsValidRunningNode = nil #@@IsLinuxCluster = nil @@KubeSystemNamespace = "kube-system" + + # TODO: refactor this so that env can be passed in (For unit tests) @os_type = Test_registry.instance.env["OS_TYPE"] if !@os_type.nil? && !@os_type.empty? && @os_type.strip.casecmp("windows") == 0 @LogPath = Constants::WINDOWS_LOG_PATH + "kubernetes_client_log.txt" diff --git a/source/plugins/ruby/filter_cadvisor2mdm.rb b/source/plugins/ruby/filter_cadvisor2mdm.rb index 902ce4bcf..3d249f513 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm.rb @@ -13,7 +13,6 @@ module Fluent::Plugin require_relative "MdmMetricsGenerator" require_relative "in_kube_nodes" require_relative "constants" - require_relative "test_registry" require 'byebug' class CAdvisor2MdmFilter < Filter @@ -37,12 +36,6 @@ def set_hostname (hostname) def initialize super - - @@isWindows = false - @@os_type = Test_registry.instance.env["OS_TYPE"] - if !@@os_type.nil? && !@@os_type.empty? && @@os_type.strip.casecmp("windows") == 0 - @@isWindows = true - end end def configure(conf) @@ -55,11 +48,22 @@ def configure(conf) end end - def start + def start(env=ENV, applicationInsightsUtility=ApplicationInsightsUtility, kubernetesApiClient=KubernetesApiClient, kubeletUtils=KubeletUtils) + @ENV = env + @AplicationInsightsUtility = applicationInsightsUtility + @KubernetesAPIClient = kubernetesApiClient + @KubeletUtils = kubeletUtils byebug super + + @@isWindows = false + @@os_type = @ENV["OS_TYPE"] + if !@@os_type.nil? && !@@os_type.empty? && @@os_type.strip.casecmp("windows") == 0 + @@isWindows = true + end + begin - @process_incoming_stream = CustomMetricsUtils.check_custom_metrics_availability + @process_incoming_stream = CustomMetricsUtils.check_custom_metrics_availability(env=@ENV) @metrics_to_collect_hash = build_metrics_hash(@metrics_to_collect) @Log.debug "After check_custom_metrics_availability process_incoming_stream #{@process_incoming_stream}" @@containerResourceUtilTelemetryTimeTracker = DateTime.now.to_time.to_i @@ -115,7 +119,7 @@ def setThresholdExceededTelemetry(metricName) end rescue => errorStr @Log.info "Error in setThresholdExceededTelemetry: #{errorStr}" - Test_registry.instance.applicationInsightsUtility.sendExceptionTelemetry(errorStr) + @ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) end end @@ -133,7 +137,7 @@ def flushMetricTelemetry properties["CpuThresholdExceededInLastFlushInterval"] = @containersExceededCpuThreshold properties["MemRssThresholdExceededInLastFlushInterval"] = @containersExceededMemRssThreshold properties["MemWSetThresholdExceededInLastFlushInterval"] = @containersExceededMemWorkingSetThreshold - Test_registry.instance.applicationInsightsUtility.sendCustomEvent(Constants::CONTAINER_RESOURCE_UTIL_HEART_BEAT_EVENT, properties) + @ApplicationInsightsUtility.sendCustomEvent(Constants::CONTAINER_RESOURCE_UTIL_HEART_BEAT_EVENT, properties) @containersExceededCpuThreshold = false @containersExceededMemRssThreshold = false @containersExceededMemWorkingSetThreshold = false @@ -141,7 +145,7 @@ def flushMetricTelemetry end rescue => errorStr @Log.info "Error in flushMetricTelemetry: #{errorStr} for container resource util telemetry" - Test_registry.instance.applicationInsightsUtility.sendExceptionTelemetry(errorStr) + @ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) end # Also send for PV usage metrics @@ -153,14 +157,14 @@ def flushMetricTelemetry pvProperties = {} pvProperties["PVUsageThresholdPercentage"] = @@metric_threshold_hash[Constants::PV_USED_BYTES] pvProperties["PVUsageThresholdExceededInLastFlushInterval"] = @pvExceededUsageThreshold - Test_registry.instance.applicationInsightsUtility.sendCustomEvent(Constants::PV_USAGE_HEART_BEAT_EVENT, pvProperties) + @ApplicationInsightsUtility.sendCustomEvent(Constants::PV_USAGE_HEART_BEAT_EVENT, pvProperties) @pvExceededUsageThreshold = false @@pvUsageTelemetryTimeTracker = DateTime.now.to_time.to_i end end rescue => errorStr @Log.info "Error in flushMetricTelemetry: #{errorStr} for PV usage telemetry" - Test_registry.instance.applicationInsightsUtility.sendExceptionTelemetry(errorStr) + @ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) end end @@ -232,14 +236,14 @@ def filter(tag, time, record) telemetryProperties["Computer"] = record["Host"] telemetryProperties["MetricName"] = metric_name telemetryProperties["MetricPercentageValue"] = percentage_metric_value - Test_registry.instance.applicationInsightsUtility.sendCustomEvent("ErrorPercentageOutOfBounds", telemetryProperties) + @ApplicationInsightsUtility.sendCustomEvent("ErrorPercentageOutOfBounds", telemetryProperties) end if allocatable_percentage_metric_value > 100.0 telemetryProperties = {} telemetryProperties["Computer"] = record["Host"] telemetryProperties["MetricName"] = metric_name telemetryProperties["MetricAllocatablePercentageValue"] = allocatable_percentage_metric_value - Test_registry.instance.applicationInsightsUtility.sendCustomEvent("ErrorPercentageOutOfBounds", telemetryProperties) + @ApplicationInsightsUtility.sendCustomEvent("ErrorPercentageOutOfBounds", telemetryProperties) end return MdmMetricsGenerator.getNodeResourceMetricRecords(record, metric_name, metric_value, percentage_metric_value, allocatable_percentage_metric_value) @@ -295,7 +299,7 @@ def filter(tag, time, record) end #end if block for process incoming stream check rescue Exception => e @Log.info "Error processing cadvisor record Exception: #{e.class} Message: #{e.message}" - Test_registry.instance.applicationInsightsUtility.sendExceptionTelemetry(e.backtrace) + @ApplicationInsightsUtility.sendExceptionTelemetry(e.backtrace) return [] #return empty array if we ran into any errors end end @@ -333,13 +337,13 @@ def filterPVInsightsMetrics(record) return [] rescue Exception => e @Log.info "Error processing cadvisor insights metrics record Exception: #{e.class} Message: #{e.message}" - Test_registry.instance.applicationInsightsUtility.sendExceptionTelemetry(e.backtrace) + @ApplicationInsightsUtility.sendExceptionTelemetry(e.backtrace) return [] #return empty array if we ran into any errors end end def ensure_cpu_memory_capacity_and_allocatable_set - @@controller_type = Test_registry.instance.env["CONTROLLER_TYPE"] + @@controller_type = @ENV["CONTROLLER_TYPE"] if @cpu_capacity != 0.0 && @memory_capacity != 0.0 && @@controller_type.downcase == "replicaset" @Log.info "CPU And Memory Capacity are already set and their values are as follows @cpu_capacity : #{@cpu_capacity}, @memory_capacity: #{@memory_capacity}" @@ -357,14 +361,14 @@ def ensure_cpu_memory_capacity_and_allocatable_set begin byebug - resourceUri = Test_registry.instance.kubernetesApiClient.getNodesResourceUri("nodes?fieldSelector=metadata.name%3D#{@@hostName}") - nodeInventory = JSON.parse(Test_registry.instance.kubernetesApiClient.getKubeResourceInfo(resourceUri).body) + resourceUri = @KubernetesAPIClient.getNodesResourceUri("nodes?fieldSelector=metadata.name%3D#{@@hostName}") + nodeInventory = JSON.parse(@KubernetesAPIClient.getKubeResourceInfo(resourceUri).body) rescue Exception => e @Log.info "Error when getting nodeInventory from kube API. Exception: #{e.class} Message: #{e.message} " - Test_registry.instance.applicationInsightsUtility.sendExceptionTelemetry(e.backtrace) + @ApplicationInsightsUtility.sendExceptionTelemetry(e.backtrace) end if !nodeInventory.nil? - cpu_capacity_json = Test_registry.instance.kubernetesApiClient.parseNodeLimits(nodeInventory, "capacity", "cpu", "cpuCapacityNanoCores") + cpu_capacity_json = @KubernetesAPIClient.parseNodeLimits(nodeInventory, "capacity", "cpu", "cpuCapacityNanoCores") if !cpu_capacity_json.nil? metricVal = JSON.parse(cpu_capacity_json[0]["json_Collections"])[0]["Value"] if !metricVal.to_s.nil? @@ -374,7 +378,7 @@ def ensure_cpu_memory_capacity_and_allocatable_set else @Log.info "Error getting cpu_capacity" end - memory_capacity_json = Test_registry.instance.kubernetesApiClient.parseNodeLimits(nodeInventory, "capacity", "memory", "memoryCapacityBytes") + memory_capacity_json = @KubernetesAPIClient.parseNodeLimits(nodeInventory, "capacity", "memory", "memoryCapacityBytes") if !memory_capacity_json.nil? metricVal = JSON.parse(cpu_capacity_json[0]["json_Collections"])[0]["Value"] if !metricVal.to_s.nil? @@ -386,7 +390,7 @@ def ensure_cpu_memory_capacity_and_allocatable_set end end elsif @@controller_type.downcase == "daemonset" - capacity_from_kubelet = Test_registry.instance.kubeletUtils.get_node_capacity + capacity_from_kubelet = @KubeletUtils.get_node_capacity # Error handling in case /metrics/cadvsior endpoint fails if !capacity_from_kubelet.nil? && capacity_from_kubelet.length > 1 @@ -397,7 +401,7 @@ def ensure_cpu_memory_capacity_and_allocatable_set @Log.error "Error getting capacity_from_kubelet: cpu_capacity and memory_capacity" end - allocatable_from_kubelet = Test_registry.instance.kubeletUtils.get_node_allocatable(@cpu_capacity, @memory_capacity) + allocatable_from_kubelet = @KubeletUtils.get_node_allocatable(@cpu_capacity, @memory_capacity) # Error handling in case /configz endpoint fails if !allocatable_from_kubelet.nil? && allocatable_from_kubelet.length > 1 diff --git a/source/plugins/ruby/filter_cadvisor2mdm_test.rb b/source/plugins/ruby/filter_cadvisor2mdm_test.rb index 421fd4cb1..71da3245e 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm_test.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm_test.rb @@ -1,3 +1,4 @@ +# TODO: can we get rid of this global flag $in_unit_test = true require "test-unit" @@ -5,7 +6,6 @@ require 'fluent/test/driver/filter' require 'fluent/test/helpers' require_relative 'filter_cadvisor2mdm.rb' -require_relative 'test_registry' require_relative 'KubernetesApiClient' require 'byebug' @@ -23,7 +23,6 @@ def create_driver(conf = "") # A relatively simple test for a helper method test "build_metrics_hash" do - instance = create_driver.instance expected = {"constants::cpu_usage_nano_cores" => true, "constants::memory_working_set_bytes" => true, "constants::memory_rss_bytes"=> true, "constants::pv_used_bytes"=> true} @@ -32,7 +31,7 @@ def create_driver(conf = "") assert_equal({}, instance.build_metrics_hash("")) - assert_equal({"foobar" => true}, instance.build_metrics_hash("foobar")) + assert_equal({"test_input:.<>" => true}, instance.build_metrics_hash("test_input:.<>")) end @@ -69,7 +68,7 @@ def getKubeResourceInfo(resource, api_group: nil) end end - Test_registry.instance.env = {"CONTROLLER_TYPE" => "ReplicaSet", + env = {"CONTROLLER_TYPE" => "ReplicaSet", "OS_TYPE" => "linux", "AZMON_ALERT_CONTAINER_CPU_THRESHOLD" => Constants::DEFAULT_MDM_CPU_UTILIZATION_THRESHOLD.to_s, "AZMON_ALERT_CONTAINER_MEMORY_RSS_THRESHOLD" => Constants::DEFAULT_MDM_MEMORY_RSS_THRESHOLD.to_s, @@ -79,8 +78,8 @@ def getKubeResourceInfo(resource, api_group: nil) "AKS_REGION" => "westus2", "AKS_RESOURCE_ID" => "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/rg/providers/Microsoft.ContainerService/managedClusters/clustername", "CLOUD_ENVIRONMENT" => "azurepubliccloud"} # TODO: this is actually set to public in running containers. Figure out how @process_incoming_stream resolves to true - Test_registry.instance.applicationInsightsUtility = Ai_utility_stub.new() - Test_registry.instance.kubernetesApiClient = KubernetesApiClientMock + applicationInsightsUtility = Ai_utility_stub.new() + kubernetesApiClient = KubernetesApiClientMock config = %[ metrics_to_collect cpuUsageNanoCores,memoryWorkingSetBytes,pvUsedBytes @@ -97,7 +96,7 @@ def getKubeResourceInfo(resource, api_group: nil) d = create_driver(config) d.instance.set_hostname("aks-nodepool1-24816391-vmss000000") - d.instance.start # TODO: why doesn't the fluentd test harness do this automatically? + d.instance.start(env=env, applicationInsightsUtility=applicationInsightsUtility, kubernetesApiClient=kubernetesApiClient) # TODO: why doesn't the fluentd test harness do this automatically? time = event_time d.run do @@ -108,6 +107,7 @@ def getKubeResourceInfo(resource, api_group: nil) puts d.filtered_records assert_equal(0, d.filtered_records.size) + assert_equal("expected response"), d.filtered_records) end end \ No newline at end of file diff --git a/test/unit-tests/run_ruby_tests.sh b/test/unit-tests/run_ruby_tests.sh index db3c3e81c..2918ab3fb 100644 --- a/test/unit-tests/run_ruby_tests.sh +++ b/test/unit-tests/run_ruby_tests.sh @@ -1,5 +1,5 @@ cd ../../source/plugins/ruby - +ruby filter_cadvisor2mdm_tests.rb cd - From 33a4a39b70d261769c229dfa7d7b3e53cedc4d7f Mon Sep 17 00:00:00 2001 From: David Michelman Date: Wed, 11 Aug 2021 20:22:41 -0700 Subject: [PATCH 10/33] fixing workflow file --- .github/workflows/run_unit_tests.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index eee621602..b917acf96 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -1,5 +1,10 @@ name: Run Unit Tests -on: [opened, synchronize, reopened] +on: + pull_request: + types: [opened, synchronize, reopened] + branches: + - ci_dev + - ci_prod jobs: Actions-Demo: runs-on: ubuntu-latest From 523d87df6d72bdd6b94d2774731d01631de414dd Mon Sep 17 00:00:00 2001 From: David Michelman Date: Wed, 11 Aug 2021 20:25:07 -0700 Subject: [PATCH 11/33] test --- .github/workflows/run_unit_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index b917acf96..59264db5d 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -31,7 +31,7 @@ jobs: - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." - name: List files in the repository run: | - cd Docker-Provider + cd ${{ github.workspace }} ./test/unit-tests/run_go_tests.sh - run: echo "🍏 This job's status is ${{ job.status }}." Ruby-Tests: From f36853a15c0e0c3eea324d6f170d9e74fc3d5994 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Wed, 11 Aug 2021 20:30:04 -0700 Subject: [PATCH 12/33] test --- test/unit-tests/run_go_tests.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/unit-tests/run_go_tests.sh b/test/unit-tests/run_go_tests.sh index acc492e62..d8649bd33 100755 --- a/test/unit-tests/run_go_tests.sh +++ b/test/unit-tests/run_go_tests.sh @@ -1,5 +1,7 @@ -cd ../../source/plugins/go/src +OLD_PATH=$(pwd) +SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +cd $SCRIPTPATH/../../source/plugins/go/src go test . -cd - +cd $OLD_PATH From b92c779134a7590eec27a1fde82ca51054ab2a66 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Wed, 11 Aug 2021 20:33:32 -0700 Subject: [PATCH 13/33] testing again --- .github/workflows/run_unit_tests.yml | 32 ++++------------------------ test/unit-tests/run_ruby_tests.sh | 6 ++++-- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index 59264db5d..0e5b520c6 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -6,45 +6,21 @@ on: - ci_dev - ci_prod jobs: - Actions-Demo: - runs-on: ubuntu-latest - steps: - - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." - - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!" - - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}." - - name: Check out repository code - uses: actions/checkout@v2 - - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." - - run: echo "🖥️ The workflow is now ready to test your code on the runner." - - name: List files in the repository - run: | - ls ${{ github.workspace }} - - run: echo "🍏 This job's status is ${{ job.status }}." Golang-Tests: runs-on: ubuntu-latest steps: - - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." - - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!" - - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}." - name: Check out repository code uses: actions/checkout@v2 - - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." - - name: List files in the repository + - name: Run unit tests run: | cd ${{ github.workspace }} ./test/unit-tests/run_go_tests.sh - - run: echo "🍏 This job's status is ${{ job.status }}." Ruby-Tests: runs-on: ubuntu-latest steps: - - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." - - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!" - - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}." - name: Check out repository code uses: actions/checkout@v2 - - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." - - run: echo "🖥️ The workflow is now ready to test your code on the runner." - - name: List files in the repository + - name: Run unit tests run: | - ls ${{ github.workspace }} - - run: echo "🍏 This job's status is ${{ job.status }}." \ No newline at end of file + cd ${{ github.workspace }} + ./test/unit-tests/run_ruby_tests.sh \ No newline at end of file diff --git a/test/unit-tests/run_ruby_tests.sh b/test/unit-tests/run_ruby_tests.sh index 2918ab3fb..c78162159 100644 --- a/test/unit-tests/run_ruby_tests.sh +++ b/test/unit-tests/run_ruby_tests.sh @@ -1,5 +1,7 @@ -cd ../../source/plugins/ruby +OLD_PATH=$(pwd) +SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +cd $SCRIPTPATH/../../source/plugins/ruby ruby filter_cadvisor2mdm_tests.rb -cd - +cd $OLD_PATH From fd41f571f810e4b4943da843233277c23f940c75 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Thu, 12 Aug 2021 10:00:00 -0700 Subject: [PATCH 14/33] making ruby test script executable --- test/unit-tests/run_ruby_tests.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 test/unit-tests/run_ruby_tests.sh diff --git a/test/unit-tests/run_ruby_tests.sh b/test/unit-tests/run_ruby_tests.sh old mode 100644 new mode 100755 From 7eec628bdbfd9f47adea1dc8032910f26a103024 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Thu, 12 Aug 2021 13:05:19 -0700 Subject: [PATCH 15/33] got rid of global object registry, still have the flag though --- source/plugins/ruby/KubernetesApiClient.rb | 43 +++++++++++-------- source/plugins/ruby/MdmMetricsGenerator.rb | 5 +-- source/plugins/ruby/filter_cadvisor2mdm.rb | 2 +- .../plugins/ruby/filter_cadvisor2mdm_test.rb | 2 +- test/unit-tests/run_ruby_tests.sh | 2 +- 5 files changed, 29 insertions(+), 25 deletions(-) diff --git a/source/plugins/ruby/KubernetesApiClient.rb b/source/plugins/ruby/KubernetesApiClient.rb index e118aa320..dbc9f35f2 100644 --- a/source/plugins/ruby/KubernetesApiClient.rb +++ b/source/plugins/ruby/KubernetesApiClient.rb @@ -27,7 +27,12 @@ class KubernetesApiClient @@KubeSystemNamespace = "kube-system" # TODO: refactor this so that env can be passed in (For unit tests) - @os_type = Test_registry.instance.env["OS_TYPE"] + # options: + # 1. make it a singleton, first call to a function which uses the logger initializes it with the correct OS type + # 2. don't change anything. (do we care if unit tests can tell which OS they're running on?) + # 3. Keep some global state (like the object registry) + # this also needs to be changed in MdmMetricsGenerator.rb (and probably most other places which use the logger) + @os_type = ENV["OS_TYPE"] if !@os_type.nil? && !@os_type.empty? && @os_type.strip.casecmp("windows") == 0 @LogPath = Constants::WINDOWS_LOG_PATH + "kubernetes_client_log.txt" else @@ -89,42 +94,42 @@ def getTokenStr end end - def getClusterRegion - if Test_registry.instance.env["AKS_REGION"] - return Test_registry.instance.env["AKS_REGION"] + def getClusterRegion(env=ENV) + if env["AKS_REGION"] + return env["AKS_REGION"] else @Log.warn ("Kubernetes environment variable not set AKS_REGION. Unable to get cluster region.") return nil end end - def getResourceUri(resource, api_group) + def getResourceUri(resource, api_group, env=ENV) begin - if Test_registry.instance.env["KUBERNETES_SERVICE_HOST"] && Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"] + if env["KUBERNETES_SERVICE_HOST"] && env["KUBERNETES_PORT_443_TCP_PORT"] if api_group.nil? - return "https://#{Test_registry.instance.env["KUBERNETES_SERVICE_HOST"]}:#{Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"]}/api/" + @@ApiVersion + "/" + resource + return "https://#{env["KUBERNETES_SERVICE_HOST"]}:#{env["KUBERNETES_PORT_443_TCP_PORT"]}/api/" + @@ApiVersion + "/" + resource elsif api_group == @@ApiGroupApps - return "https://#{Test_registry.instance.env["KUBERNETES_SERVICE_HOST"]}:#{Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"]}/apis/apps/" + @@ApiVersionApps + "/" + resource + return "https://#{env["KUBERNETES_SERVICE_HOST"]}:#{env["KUBERNETES_PORT_443_TCP_PORT"]}/apis/apps/" + @@ApiVersionApps + "/" + resource elsif api_group == @@ApiGroupHPA - return "https://#{Test_registry.instance.env["KUBERNETES_SERVICE_HOST"]}:#{Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"]}/apis/" + @@ApiGroupHPA + "/" + @@ApiVersionHPA + "/" + resource + return "https://#{env["KUBERNETES_SERVICE_HOST"]}:#{env["KUBERNETES_PORT_443_TCP_PORT"]}/apis/" + @@ApiGroupHPA + "/" + @@ApiVersionHPA + "/" + resource end else - @Log.warn ("Kubernetes environment variable not set KUBERNETES_SERVICE_HOST: #{Test_registry.instance.env["KUBERNETES_SERVICE_HOST"]} KUBERNETES_PORT_443_TCP_PORT: #{Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"]}. Unable to form resourceUri") + @Log.warn ("Kubernetes environment variable not set KUBERNETES_SERVICE_HOST: #{env["KUBERNETES_SERVICE_HOST"]} KUBERNETES_PORT_443_TCP_PORT: #{env["KUBERNETES_PORT_443_TCP_PORT"]}. Unable to form resourceUri") return nil end end end - def getClusterName + def getClusterName(env=ENV) return @@ClusterName if !@@ClusterName.nil? @@ClusterName = "None" begin #try getting resource ID for aks - cluster = Test_registry.instance.env["AKS_RESOURCE_ID"] + cluster = env["AKS_RESOURCE_ID"] if cluster && !cluster.nil? && !cluster.empty? @@ClusterName = cluster.split("/").last else - cluster = Test_registry.instance.env["ACS_RESOURCE_NAME"] + cluster = env["ACS_RESOURCE_NAME"] if cluster && !cluster.nil? && !cluster.empty? @@ClusterName = cluster else @@ -149,7 +154,7 @@ def getClusterName return @@ClusterName end - def getClusterId + def getClusterId(env=ENV) return @@ClusterId if !@@ClusterId.nil? #By default initialize ClusterId to ClusterName. # In ACS/On-prem, we need to figure out how we can generate ClusterId @@ -157,7 +162,7 @@ def getClusterId # e.g. md5 digest is 128 bits = 32 character in hex. Get first 16 and get a guid, and the next 16 to get resource id @@ClusterId = getClusterName begin - cluster = Test_registry.instance.env["AKS_RESOURCE_ID"] + cluster = env["AKS_RESOURCE_ID"] if cluster && !cluster.nil? && !cluster.empty? @@ClusterId = cluster end @@ -779,13 +784,13 @@ def getResourcesAndContinuationToken(uri, api_group: nil) return continuationToken, resourceInventory end #getResourcesAndContinuationToken - def getKubeAPIServerUrl + def getKubeAPIServerUrl(env=ENV) apiServerUrl = nil begin - if Test_registry.instance.env["KUBERNETES_SERVICE_HOST"] && Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"] - apiServerUrl = "https://#{Test_registry.instance.env["KUBERNETES_SERVICE_HOST"]}:#{Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"]}" + if env["KUBERNETES_SERVICE_HOST"] && env["KUBERNETES_PORT_443_TCP_PORT"] + apiServerUrl = "https://#{env["KUBERNETES_SERVICE_HOST"]}:#{env["KUBERNETES_PORT_443_TCP_PORT"]}" else - @Log.warn "Kubernetes environment variable not set KUBERNETES_SERVICE_HOST: #{Test_registry.instance.env["KUBERNETES_SERVICE_HOST"]} KUBERNETES_PORT_443_TCP_PORT: #{Test_registry.instance.env["KUBERNETES_PORT_443_TCP_PORT"]}. Unable to form resourceUri" + @Log.warn "Kubernetes environment variable not set KUBERNETES_SERVICE_HOST: #{env["KUBERNETES_SERVICE_HOST"]} KUBERNETES_PORT_443_TCP_PORT: #{env["KUBERNETES_PORT_443_TCP_PORT"]}. Unable to form resourceUri" end rescue => errorStr @Log.warn "KubernetesApiClient::getKubeAPIServerUrl:Failed #{errorStr}" diff --git a/source/plugins/ruby/MdmMetricsGenerator.rb b/source/plugins/ruby/MdmMetricsGenerator.rb index 93004688e..a4fdfbc92 100644 --- a/source/plugins/ruby/MdmMetricsGenerator.rb +++ b/source/plugins/ruby/MdmMetricsGenerator.rb @@ -9,9 +9,8 @@ class MdmMetricsGenerator require_relative "ApplicationInsightsUtility" require_relative "constants" require_relative "oms_common" - require_relative "test_registry" - @os_type = Test_registry.instance.env["OS_TYPE"] + @os_type = ENV["OS_TYPE"] if !@os_type.nil? && !@os_type.empty? && @os_type.strip.casecmp("windows") == 0 @log_path = Constants::WINDOWS_LOG_PATH + "mdm_metrics_generator.log" else @@ -486,7 +485,7 @@ def is_numeric(o) true if Float(o) rescue false end - def getContainerResourceUtilizationThresholds + def getContainerResourceUtilizationThresholds(env=ENV) begin metric_threshold_hash = {} # Initilizing with default values diff --git a/source/plugins/ruby/filter_cadvisor2mdm.rb b/source/plugins/ruby/filter_cadvisor2mdm.rb index 3d249f513..aadfd6db3 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm.rb @@ -54,7 +54,7 @@ def start(env=ENV, applicationInsightsUtility=ApplicationInsightsUtility, kubern @KubernetesAPIClient = kubernetesApiClient @KubeletUtils = kubeletUtils byebug - super + super() @@isWindows = false @@os_type = @ENV["OS_TYPE"] diff --git a/source/plugins/ruby/filter_cadvisor2mdm_test.rb b/source/plugins/ruby/filter_cadvisor2mdm_test.rb index 71da3245e..58a3a8801 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm_test.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm_test.rb @@ -107,7 +107,7 @@ def getKubeResourceInfo(resource, api_group: nil) puts d.filtered_records assert_equal(0, d.filtered_records.size) - assert_equal("expected response"), d.filtered_records) + # assert_equal("expected response", d.filtered_records) end end \ No newline at end of file diff --git a/test/unit-tests/run_ruby_tests.sh b/test/unit-tests/run_ruby_tests.sh index c78162159..6896a2249 100755 --- a/test/unit-tests/run_ruby_tests.sh +++ b/test/unit-tests/run_ruby_tests.sh @@ -2,6 +2,6 @@ OLD_PATH=$(pwd) SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" cd $SCRIPTPATH/../../source/plugins/ruby -ruby filter_cadvisor2mdm_tests.rb +ruby filter_cadvisor2mdm_test.rb cd $OLD_PATH From dc009d1317c9c10fb8474b365d295fb9070ded2f Mon Sep 17 00:00:00 2001 From: David Michelman Date: Fri, 13 Aug 2021 17:54:16 -0700 Subject: [PATCH 16/33] more complex go unit test with mocking --- source/plugins/go/src/extension/extension.go | 47 +++---- .../go/src/extension/extension_test.go | 84 ++++++++++++ .../go/src/extension/mock_socket_writer.go | 122 ++++++++++++++++++ .../plugins/go/src/extension/socket_writer.go | 54 +++++--- source/plugins/go/src/go.mod | 4 +- source/plugins/go/src/go.sum | 27 ++++ source/plugins/go/src/utils.go | 121 ++++++++--------- source/plugins/go/src/utils_test.go | 47 +++++++ source/plugins/ruby/MdmMetricsGenerator.rb | 10 +- source/plugins/ruby/filter_cadvisor2mdm.rb | 10 +- test/unit-tests/run_ruby_tests.sh | 2 +- 11 files changed, 418 insertions(+), 110 deletions(-) create mode 100644 source/plugins/go/src/extension/extension_test.go create mode 100644 source/plugins/go/src/extension/mock_socket_writer.go diff --git a/source/plugins/go/src/extension/extension.go b/source/plugins/go/src/extension/extension.go index c68140ded..4cf7f8ccd 100644 --- a/source/plugins/go/src/extension/extension.go +++ b/source/plugins/go/src/extension/extension.go @@ -1,12 +1,13 @@ package extension -import ( +import ( "encoding/json" "fmt" - "log" + "log" + "strings" "sync" - "strings" - uuid "github.com/google/uuid" + + uuid "github.com/google/uuid" "github.com/ugorji/go/codec" ) @@ -14,31 +15,31 @@ type Extension struct { datatypeStreamIdMap map[string]string } -var singleton *Extension +var singleton *Extension var once sync.Once var extensionconfiglock sync.Mutex var logger *log.Logger -var containerType string +var containerType string func GetInstance(flbLogger *log.Logger, containerType string) *Extension { - once.Do(func() { - singleton = &Extension{make(map[string]string)} + once.Do(func() { + singleton = &Extension{make(map[string]string)} flbLogger.Println("Extension Instance created") - }) + }) logger = flbLogger containerType = containerType - return singleton + return singleton } func (e *Extension) GetOutputStreamId(datatype string) string { extensionconfiglock.Lock() - defer extensionconfiglock.Unlock() + defer extensionconfiglock.Unlock() if len(e.datatypeStreamIdMap) > 0 && e.datatypeStreamIdMap[datatype] != "" { message := fmt.Sprintf("OutputstreamId: %s for the datatype: %s", e.datatypeStreamIdMap[datatype], datatype) logger.Printf(message) return e.datatypeStreamIdMap[datatype] } - var err error + var err error e.datatypeStreamIdMap, err = getDataTypeToStreamIdMapping() if err != nil { message := fmt.Sprintf("Error getting datatype to streamid mapping: %s", err.Error()) @@ -56,18 +57,18 @@ func getDataTypeToStreamIdMapping() (map[string]string, error) { jsonBytes, err := json.Marshal(taggedData) var data []byte - enc := codec.NewEncoderBytes(&data, new(codec.MsgpackHandle)) + enc := codec.NewEncoderBytes(&data, new(codec.MsgpackHandle)) if err := enc.Encode(string(jsonBytes)); err != nil { return datatypeOutputStreamMap, err } - - fs := &FluentSocketWriter{ } + + fs := FluentSocket{} fs.sockAddress = "/var/run/mdsd/default_fluent.socket" if containerType != "" && strings.Compare(strings.ToLower(containerType), "prometheussidecar") == 0 { fs.sockAddress = fmt.Sprintf("/var/run/mdsd-%s/default_fluent.socket", containerType) - } - responseBytes, err := fs.WriteAndRead(data) - defer fs.disConnect() + } + responseBytes, err := FluentSocketWriter.WriteAndRead(fs, data) + defer FluentSocketWriter.disConnect(fs) logger.Printf("Info::mdsd::Making call to FluentSocket: %s to write and read the config data", fs.sockAddress) if err != nil { return datatypeOutputStreamMap, err @@ -76,7 +77,7 @@ func getDataTypeToStreamIdMapping() (map[string]string, error) { var responseObjet AgentTaggedDataResponse err = json.Unmarshal([]byte(response), &responseObjet) - if err != nil { + if err != nil { logger.Printf("Error::mdsd::Failed to unmarshal config data. Error message: %s", string(err.Error())) return datatypeOutputStreamMap, err } @@ -84,16 +85,16 @@ func getDataTypeToStreamIdMapping() (map[string]string, error) { var extensionData TaggedData json.Unmarshal([]byte(responseObjet.TaggedData), &extensionData) - extensionConfigs := extensionData.ExtensionConfigs - logger.Printf("Info::mdsd::build the datatype and streamid map -- start") + extensionConfigs := extensionData.ExtensionConfigs + logger.Printf("Info::mdsd::build the datatype and streamid map -- start") for _, extensionConfig := range extensionConfigs { outputStreams := extensionConfig.OutputStreams for dataType, outputStreamID := range outputStreams { logger.Printf("Info::mdsd::datatype: %s, outputstreamId: %s", dataType, outputStreamID) datatypeOutputStreamMap[dataType] = outputStreamID.(string) - } + } } - logger.Printf("Info::mdsd::build the datatype and streamid map -- end") + logger.Printf("Info::mdsd::build the datatype and streamid map -- end") logger.Printf("extensionconfig::getDataTypeToStreamIdMapping:: getting extension config from fluent socket-end") diff --git a/source/plugins/go/src/extension/extension_test.go b/source/plugins/go/src/extension/extension_test.go new file mode 100644 index 000000000..05aa30622 --- /dev/null +++ b/source/plugins/go/src/extension/extension_test.go @@ -0,0 +1,84 @@ +package extension + +import ( + "testing" + + "github.com/golang/mock/gomock" +) + +// func Test_isValidUrl(t *testing.T) { +// type test_struct struct { +// isValid bool +// url string +// } + +// tests := []test_struct{ +// {true, "https://www.microsoft.com"}, +// {true, "http://abc.xyz"}, +// {true, "https://www.microsoft.com/tests"}, +// {false, "()"}, +// {false, "https//www.microsoft.com"}, +// {false, "https:/www.microsoft.com"}, +// {false, "https:/www.microsoft.com*"}, +// {false, ""}, +// } + +// for _, tt := range tests { +// t.Run(tt.url, func(t *testing.T) { +// got := isValidUrl(tt.url) +// if got != tt.isValid { +// t.Errorf("isValidUrl(%s) = %t, want %t", tt.url, got, tt.isValid) +// } +// }) +// } +// } + +type FluentSocketWriterMock struct{} + +func Test_getDataTypeToStreamIdMapping(t *testing.T) { + + type test_struct struct { + testName string + mdsdResponse string + fluentSocket FluentSocket + output map[string]string + err error + } + + tests := []test_struct{ + { + "basic test", + "asdfasdfasdfasdfasdf not valid json", + FluentSocket{}, + map[string]string{"a": "b"}, + nil, + }, + } + + for _, tt := range tests { + t.Run(tt.testName, func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + mock := NewMockIFluentSocketWriter(mockCtrl) + sock := FluentSocket{} + mock.EXPECT().WriteAndRead(sock, []byte("asdf")).Return([]byte("asdf"), nil).Times(1) + mock.WriteAndRead(sock, []byte("asdf")) + + _, err := getDataTypeToStreamIdMapping() + if err != nil { + t.Errorf("got error") + } + // if got != tt.isValid { + // t.Errorf("isValidUrl(%s) = %t, want %t", tt.url, got, tt.isValid) + // } + }) + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + mock := NewMockIFluentSocketWriter(mockCtrl) + sock := FluentSocket{} + mock.EXPECT().WriteAndRead(sock, []byte("asdf")).Return([]byte("asdf"), nil).Times(1) + mock.WriteAndRead(sock, []byte("asdf")) + +} diff --git a/source/plugins/go/src/extension/mock_socket_writer.go b/source/plugins/go/src/extension/mock_socket_writer.go new file mode 100644 index 000000000..c6e4c4ecf --- /dev/null +++ b/source/plugins/go/src/extension/mock_socket_writer.go @@ -0,0 +1,122 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: Docker-Provider/source/plugins/go/src/extension (interfaces: IFluentSocketWriter) + +// Package extension is a generated GoMock package. +package extension + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" +) + +// MockIFluentSocketWriter is a mock of IFluentSocketWriter interface. +type MockIFluentSocketWriter struct { + ctrl *gomock.Controller + recorder *MockIFluentSocketWriterMockRecorder +} + +// MockIFluentSocketWriterMockRecorder is the mock recorder for MockIFluentSocketWriter. +type MockIFluentSocketWriterMockRecorder struct { + mock *MockIFluentSocketWriter +} + +// NewMockIFluentSocketWriter creates a new mock instance. +func NewMockIFluentSocketWriter(ctrl *gomock.Controller) *MockIFluentSocketWriter { + mock := &MockIFluentSocketWriter{ctrl: ctrl} + mock.recorder = &MockIFluentSocketWriterMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockIFluentSocketWriter) EXPECT() *MockIFluentSocketWriterMockRecorder { + return m.recorder +} + +// Write mocks base method. +func (m *MockIFluentSocketWriter) Write(arg0 FluentSocket, arg1 []byte) (int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Write", arg0, arg1) + ret0, _ := ret[0].(int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Write indicates an expected call of Write. +func (mr *MockIFluentSocketWriterMockRecorder) Write(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Write", reflect.TypeOf((*MockIFluentSocketWriter)(nil).Write), arg0, arg1) +} + +// WriteAndRead mocks base method. +func (m *MockIFluentSocketWriter) WriteAndRead(arg0 FluentSocket, arg1 []byte) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WriteAndRead", arg0, arg1) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// WriteAndRead indicates an expected call of WriteAndRead. +func (mr *MockIFluentSocketWriterMockRecorder) WriteAndRead(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteAndRead", reflect.TypeOf((*MockIFluentSocketWriter)(nil).WriteAndRead), arg0, arg1) +} + +// connect mocks base method. +func (m *MockIFluentSocketWriter) connect(arg0 FluentSocket) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "connect", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// connect indicates an expected call of connect. +func (mr *MockIFluentSocketWriterMockRecorder) connect(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "connect", reflect.TypeOf((*MockIFluentSocketWriter)(nil).connect), arg0) +} + +// disConnect mocks base method. +func (m *MockIFluentSocketWriter) disConnect(arg0 FluentSocket) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "disConnect", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// disConnect indicates an expected call of disConnect. +func (mr *MockIFluentSocketWriterMockRecorder) disConnect(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "disConnect", reflect.TypeOf((*MockIFluentSocketWriter)(nil).disConnect), arg0) +} + +// read mocks base method. +func (m *MockIFluentSocketWriter) read(arg0 FluentSocket) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "read", arg0) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// read indicates an expected call of read. +func (mr *MockIFluentSocketWriterMockRecorder) read(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "read", reflect.TypeOf((*MockIFluentSocketWriter)(nil).read), arg0) +} + +// writeWithRetries mocks base method. +func (m *MockIFluentSocketWriter) writeWithRetries(arg0 FluentSocket, arg1 []byte) (int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "writeWithRetries", arg0, arg1) + ret0, _ := ret[0].(int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// writeWithRetries indicates an expected call of writeWithRetries. +func (mr *MockIFluentSocketWriterMockRecorder) writeWithRetries(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "writeWithRetries", reflect.TypeOf((*MockIFluentSocketWriter)(nil).writeWithRetries), arg0, arg1) +} diff --git a/source/plugins/go/src/extension/socket_writer.go b/source/plugins/go/src/extension/socket_writer.go index 1b16b319c..48b5c08ea 100644 --- a/source/plugins/go/src/extension/socket_writer.go +++ b/source/plugins/go/src/extension/socket_writer.go @@ -4,20 +4,42 @@ import ( "net" ) +//go:generate mockgen -destination=mock_socket_writer.go -package=extension Docker-Provider/source/plugins/go/src/extension IFluentSocketWriter + //MaxRetries for trying to write data to the socket const MaxRetries = 5 //ReadBufferSize for reading data from sockets //Current CI extension config size is ~5KB and going with 20KB to handle any future scenarios -const ReadBufferSize = 20480 +const ReadBufferSize = 20480 //FluentSocketWriter writes data to AMA's default fluent socket -type FluentSocketWriter struct { - socket net.Conn - sockAddress string +type FluentSocket struct { + socket net.Conn + sockAddress string +} + +// this is for mocking +type IFluentSocketWriter interface { + connect(fluentSocket FluentSocket) error + disConnect(fluentSocket FluentSocket) error + writeWithRetries(fluentSocket FluentSocket, data []byte) (int, error) + read(fluentSocket FluentSocket) ([]byte, error) + Write(fluentSocket FluentSocket, payload []byte) (int, error) + WriteAndRead(fluentSocket FluentSocket, payload []byte) ([]byte, error) +} + +type FluentSocketWriterImpl struct{} + +var FluentSocketWriter IFluentSocketWriter + +func init() { + FluentSocketWriter = FluentSocketWriterImpl{} } -func (fs *FluentSocketWriter) connect() error { +// end mocking boilerplate + +func (FluentSocketWriterImpl) connect(fs FluentSocket) error { c, err := net.Dial("unix", fs.sockAddress) if err != nil { return err @@ -26,15 +48,15 @@ func (fs *FluentSocketWriter) connect() error { return nil } -func (fs *FluentSocketWriter) disConnect() error { - if (fs.socket != nil) { - fs.socket.Close() +func (FluentSocketWriterImpl) disConnect(fs FluentSocket) error { + if fs.socket != nil { + fs.socket.Close() fs.socket = nil } return nil } -func (fs *FluentSocketWriter) writeWithRetries(data []byte) (int, error) { +func (FluentSocketWriterImpl) writeWithRetries(fs FluentSocket, data []byte) (int, error) { var ( err error n int @@ -54,7 +76,7 @@ func (fs *FluentSocketWriter) writeWithRetries(data []byte) (int, error) { return 0, err } -func (fs *FluentSocketWriter) read() ([]byte, error) { +func (FluentSocketWriterImpl) read(fs FluentSocket) ([]byte, error) { buf := make([]byte, ReadBufferSize) n, err := fs.socket.Read(buf) if err != nil { @@ -64,22 +86,22 @@ func (fs *FluentSocketWriter) read() ([]byte, error) { } -func (fs *FluentSocketWriter) Write(payload []byte) (int, error) { +func (FluentSocketWriterImpl) Write(fs FluentSocket, payload []byte) (int, error) { if fs.socket == nil { // previous write failed with permanent error and socket was closed. - if err := fs.connect(); err != nil { + if err := FluentSocketWriter.connect(fs); err != nil { return 0, err } } - return fs.writeWithRetries(payload) + return FluentSocketWriter.writeWithRetries(fs, payload) } //WriteAndRead writes data to the socket and sends the response back -func (fs *FluentSocketWriter) WriteAndRead(payload []byte) ([]byte, error) { - _, err := fs.Write(payload) +func (FluentSocketWriterImpl) WriteAndRead(fs FluentSocket, payload []byte) ([]byte, error) { + _, err := FluentSocketWriter.Write(fs, payload) if err != nil { return nil, err } - return fs.read() + return FluentSocketWriter.read(fs) } diff --git a/source/plugins/go/src/go.mod b/source/plugins/go/src/go.mod index db29a0553..f8e3db01a 100644 --- a/source/plugins/go/src/go.mod +++ b/source/plugins/go/src/go.mod @@ -10,6 +10,7 @@ require ( github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680 // indirect github.com/gogo/protobuf v0.0.0-20170330071051-c0656edd0d9e // indirect github.com/golang/glog v0.0.0-20141105023935-44145f04b68c // indirect + github.com/golang/mock v1.6.0 github.com/google/btree v0.0.0-20160524151835-7d79101e329e // indirect github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367 // indirect github.com/google/uuid v1.1.1 @@ -24,12 +25,11 @@ require ( github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b // indirect github.com/tinylib/msgp v1.1.2 github.com/ugorji/go v1.1.2-0.20180813092308-00b869d2f4a5 - golang.org/x/net v0.0.0-20200421231249-e086a090c8fd // indirect + golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f golang.org/x/time v0.0.0-20161028155119-f51c12702a4d // indirect gopkg.in/inf.v0 v0.9.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3 k8s.io/api v0.0.0-20180628040859-072894a440bd // indirect k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d k8s.io/client-go v8.0.0+incompatible - golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f ) diff --git a/source/plugins/go/src/go.sum b/source/plugins/go/src/go.sum index 7e8b3d765..1a98029d1 100644 --- a/source/plugins/go/src/go.sum +++ b/source/plugins/go/src/go.sum @@ -57,6 +57,8 @@ github.com/gogo/protobuf v0.0.0-20170330071051-c0656edd0d9e h1:ago6fNuQ6IhszPsXk github.com/gogo/protobuf v0.0.0-20170330071051-c0656edd0d9e/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20141105023935-44145f04b68c h1:CbdkBQ1/PiAo0FYJhQGwASD8wrgNvTdf01g6+O9tNuA= github.com/golang/glog v0.0.0-20141105023935-44145f04b68c/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= @@ -107,24 +109,33 @@ github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/ugorji/go v1.1.2-0.20180813092308-00b869d2f4a5 h1:JRe7Bc0YQq+x7Bm3p/LIBIb4aopsdr3H0KRKRI8g6oY= github.com/ugorji/go v1.1.2-0.20180813092308-00b869d2f4a5/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20180222182404-49796115aa4b h1:/GxqO8gbyb+sNnviFY2IIMrtm8vGg6NEJDft68wJY/g= golang.org/x/crypto v0.0.0-20180222182404-49796115aa4b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f h1:aZp0e2vLN4MToVqnjNEYEtrEA8RH8U8FN1CU7JgqsPU= golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170809000501-1c05540f6879 h1:0rFa7EaCGdQPmZVbo9F7MNF65b8dyzS6EUnXjs9Cllk= golang.org/x/net v0.0.0-20170809000501-1c05540f6879/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI= golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20171031081856-95c657629925 h1:nCH33NboKIsT4HoXBsXTWX8ul303HxWgkc5s2Ezwacg= golang.org/x/sys v0.0.0-20171031081856-95c657629925/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -133,14 +144,30 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170810154203-b19bf474d317 h1:WKW+OPdYPlvOTVGHuMfjnIC6yY2SI93yFB0pZ7giBmQ= golang.org/x/text v0.0.0-20170810154203-b19bf474d317/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wktg7Jn/a/fNmr33HSj8g= golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/source/plugins/go/src/utils.go b/source/plugins/go/src/utils.go index 02d30607e..e5aa15bdd 100644 --- a/source/plugins/go/src/utils.go +++ b/source/plugins/go/src/utils.go @@ -12,8 +12,8 @@ import ( "net/url" "os" "strings" - "time" - + "time" + "github.com/Azure/azure-kusto-go/kusto" "github.com/Azure/azure-kusto-go/kusto/ingest" "github.com/Azure/go-autorest/autorest/azure/auth" @@ -87,7 +87,7 @@ func CreateHTTPClient() { } tlsConfig.BuildNameToCertificate() - transport = &http.Transport{TLSClientConfig: tlsConfig} + transport = &http.Transport{TLSClientConfig: tlsConfig} } // set the proxy if the proxy configured if ProxyEndpoint != "" { @@ -105,7 +105,7 @@ func CreateHTTPClient() { HTTPClient = http.Client{ Transport: transport, Timeout: 30 * time.Second, - } + } Log("Successfully created HTTP Client") } @@ -123,57 +123,57 @@ func ToString(s interface{}) string { //mdsdSocketClient to write msgp messages func CreateMDSDClient(dataType DataType, containerType string) { - mdsdfluentSocket := "/var/run/mdsd/default_fluent.socket" + mdsdfluentSocket := "/var/run/mdsd/default_fluent.socket" if containerType != "" && strings.Compare(strings.ToLower(containerType), "prometheussidecar") == 0 { - mdsdfluentSocket = fmt.Sprintf("/var/run/mdsd-%s/default_fluent.socket", containerType) - } + mdsdfluentSocket = fmt.Sprintf("/var/run/mdsd-%s/default_fluent.socket", containerType) + } switch dataType { - case ContainerLogV2: - if MdsdMsgpUnixSocketClient != nil { - MdsdMsgpUnixSocketClient.Close() - MdsdMsgpUnixSocketClient = nil - } - /*conn, err := fluent.New(fluent.Config{FluentNetwork:"unix", - FluentSocketPath:"/var/run/mdsd/default_fluent.socket", - WriteTimeout: 5 * time.Second, - RequestAck: true}) */ - conn, err := net.DialTimeout("unix", - mdsdfluentSocket, 10*time.Second) - if err != nil { - Log("Error::mdsd::Unable to open MDSD msgp socket connection for ContainerLogV2 %s", err.Error()) - //log.Fatalf("Unable to open MDSD msgp socket connection %s", err.Error()) - } else { - Log("Successfully created MDSD msgp socket connection for ContainerLogV2: %s", mdsdfluentSocket) - MdsdMsgpUnixSocketClient = conn - } - case KubeMonAgentEvents: - if MdsdKubeMonMsgpUnixSocketClient != nil { - MdsdKubeMonMsgpUnixSocketClient.Close() - MdsdKubeMonMsgpUnixSocketClient = nil - } - conn, err := net.DialTimeout("unix", - mdsdfluentSocket, 10*time.Second) - if err != nil { - Log("Error::mdsd::Unable to open MDSD msgp socket connection for KubeMon events %s", err.Error()) - //log.Fatalf("Unable to open MDSD msgp socket connection %s", err.Error()) - } else { - Log("Successfully created MDSD msgp socket connection for KubeMon events:%s", mdsdfluentSocket) - MdsdKubeMonMsgpUnixSocketClient = conn - } - case InsightsMetrics: - if MdsdInsightsMetricsMsgpUnixSocketClient != nil { - MdsdInsightsMetricsMsgpUnixSocketClient.Close() - MdsdInsightsMetricsMsgpUnixSocketClient = nil - } - conn, err := net.DialTimeout("unix", - mdsdfluentSocket, 10*time.Second) - if err != nil { - Log("Error::mdsd::Unable to open MDSD msgp socket connection for insights metrics %s", err.Error()) - //log.Fatalf("Unable to open MDSD msgp socket connection %s", err.Error()) - } else { - Log("Successfully created MDSD msgp socket connection for Insights metrics %s", mdsdfluentSocket) - MdsdInsightsMetricsMsgpUnixSocketClient = conn - } + case ContainerLogV2: + if MdsdMsgpUnixSocketClient != nil { + MdsdMsgpUnixSocketClient.Close() + MdsdMsgpUnixSocketClient = nil + } + /*conn, err := fluent.New(fluent.Config{FluentNetwork:"unix", + FluentSocketPath:"/var/run/mdsd/default_fluent.socket", + WriteTimeout: 5 * time.Second, + RequestAck: true}) */ + conn, err := net.DialTimeout("unix", + mdsdfluentSocket, 10*time.Second) + if err != nil { + Log("Error::mdsd::Unable to open MDSD msgp socket connection for ContainerLogV2 %s", err.Error()) + //log.Fatalf("Unable to open MDSD msgp socket connection %s", err.Error()) + } else { + Log("Successfully created MDSD msgp socket connection for ContainerLogV2: %s", mdsdfluentSocket) + MdsdMsgpUnixSocketClient = conn + } + case KubeMonAgentEvents: + if MdsdKubeMonMsgpUnixSocketClient != nil { + MdsdKubeMonMsgpUnixSocketClient.Close() + MdsdKubeMonMsgpUnixSocketClient = nil + } + conn, err := net.DialTimeout("unix", + mdsdfluentSocket, 10*time.Second) + if err != nil { + Log("Error::mdsd::Unable to open MDSD msgp socket connection for KubeMon events %s", err.Error()) + //log.Fatalf("Unable to open MDSD msgp socket connection %s", err.Error()) + } else { + Log("Successfully created MDSD msgp socket connection for KubeMon events:%s", mdsdfluentSocket) + MdsdKubeMonMsgpUnixSocketClient = conn + } + case InsightsMetrics: + if MdsdInsightsMetricsMsgpUnixSocketClient != nil { + MdsdInsightsMetricsMsgpUnixSocketClient.Close() + MdsdInsightsMetricsMsgpUnixSocketClient = nil + } + conn, err := net.DialTimeout("unix", + mdsdfluentSocket, 10*time.Second) + if err != nil { + Log("Error::mdsd::Unable to open MDSD msgp socket connection for insights metrics %s", err.Error()) + //log.Fatalf("Unable to open MDSD msgp socket connection %s", err.Error()) + } else { + Log("Successfully created MDSD msgp socket connection for Insights metrics %s", mdsdfluentSocket) + MdsdInsightsMetricsMsgpUnixSocketClient = conn + } } } @@ -201,12 +201,17 @@ func CreateADXClient() { } } +// option 1 func ReadFileContents(fullPathToFileName string) (string, error) { + return ReadFileContentsImpl(fullPathToFileName, ioutil.ReadFile) +} + +func ReadFileContentsImpl(fullPathToFileName string, readfilefunc func(string) ([]byte, error)) (string, error) { fullPathToFileName = strings.TrimSpace(fullPathToFileName) if len(fullPathToFileName) == 0 { return "", errors.New("ReadFileContents::filename is empty") } - content, err := ioutil.ReadFile(fullPathToFileName) //no need to close + content, err := readfilefunc(fullPathToFileName) //no need to close if err != nil { return "", errors.New("ReadFileContents::Unable to open file " + fullPathToFileName) } else { @@ -228,7 +233,7 @@ func isValidUrl(uri string) bool { func convertMsgPackEntriesToMsgpBytes(fluentForwardTag string, msgPackEntries []MsgPackEntry) []byte { var msgpBytes []byte - + fluentForward := MsgPackForward{ Tag: fluentForwardTag, Entries: msgPackEntries, @@ -239,7 +244,7 @@ func convertMsgPackEntriesToMsgpBytes(fluentForwardTag string, msgPackEntries [] msgpSize += 1 + msgp.Int64Size + msgp.GuessSize(fluentForward.Entries[i].Record) } - //allocate buffer for msgp message + //allocate buffer for msgp message msgpBytes = msgp.Require(nil, msgpSize) //construct the stream @@ -252,6 +257,6 @@ func convertMsgPackEntriesToMsgpBytes(fluentForwardTag string, msgPackEntries [] msgpBytes = msgp.AppendInt64(msgpBytes, batchTime) msgpBytes = msgp.AppendMapStrStr(msgpBytes, fluentForward.Entries[entry].Record) } - - return msgpBytes + + return msgpBytes } diff --git a/source/plugins/go/src/utils_test.go b/source/plugins/go/src/utils_test.go index 8d957267f..ab61ce751 100644 --- a/source/plugins/go/src/utils_test.go +++ b/source/plugins/go/src/utils_test.go @@ -1,6 +1,7 @@ package main import ( + "errors" "testing" ) @@ -30,3 +31,49 @@ func Test_isValidUrl(t *testing.T) { }) } } + +func Test_ReadFileContents(t *testing.T) { + type mock_struct struct { + expectedFilePath string + fileContents []byte + err error + } + type test_struct struct { + testname string + calledFilePath string + subcall_spec mock_struct + output string + err bool + } + + tests := []test_struct{ + {"normal", "foobar.txt", mock_struct{"foobar.txt", []byte("asdf"), nil}, "asdf", false}, + {"extra whitespace", "foobar.txt ", mock_struct{"foobar.txt", []byte("asdf \t"), nil}, "asdf", false}, + {"empty filename", "", mock_struct{"", []byte(""), nil}, "", true}, + {"file doesn't exist", "asdf.txt", mock_struct{"asdf", []byte(""), errors.New("this error doesn't matter much")}, "", true}, + } + + for _, tt := range tests { + t.Run(string(tt.testname), func(t *testing.T) { + + readfileFunc := func(filename string) ([]byte, error) { + if filename == tt.subcall_spec.expectedFilePath { + return tt.subcall_spec.fileContents, nil + } + return []byte(""), errors.New("file not found") + } + + got, err := ReadFileContentsImpl(tt.calledFilePath, readfileFunc) + + if got != tt.output || !(tt.err == (err != nil)) { + t.Errorf("ReadFileContents(%v) = (%v, %v), want (%v, %v)", tt.calledFilePath, got, err, tt.output, tt.err) + if got != tt.output { + t.Errorf("output strings are not equal") + } + if tt.err == (err != nil) { + t.Errorf("errors are not equal") + } + } + }) + } +} diff --git a/source/plugins/ruby/MdmMetricsGenerator.rb b/source/plugins/ruby/MdmMetricsGenerator.rb index a4fdfbc92..2cf0e604e 100644 --- a/source/plugins/ruby/MdmMetricsGenerator.rb +++ b/source/plugins/ruby/MdmMetricsGenerator.rb @@ -495,32 +495,32 @@ def getContainerResourceUtilizationThresholds(env=ENV) metric_threshold_hash[Constants::PV_USED_BYTES] = Constants::DEFAULT_MDM_PV_UTILIZATION_THRESHOLD metric_threshold_hash[Constants::JOB_COMPLETION_TIME] = Constants::DEFAULT_MDM_JOB_COMPLETED_TIME_THRESHOLD_MINUTES - cpuThreshold = Test_registry.instance.env["AZMON_ALERT_CONTAINER_CPU_THRESHOLD"] + cpuThreshold = env["AZMON_ALERT_CONTAINER_CPU_THRESHOLD"] if !cpuThreshold.nil? && !cpuThreshold.empty? #Rounding this to 2 decimal places, since this value is user configurable cpuThresholdFloat = (cpuThreshold.to_f).round(2) metric_threshold_hash[Constants::CPU_USAGE_NANO_CORES] = cpuThresholdFloat end - memoryRssThreshold = Test_registry.instance.env["AZMON_ALERT_CONTAINER_MEMORY_RSS_THRESHOLD"] + memoryRssThreshold = env["AZMON_ALERT_CONTAINER_MEMORY_RSS_THRESHOLD"] if !memoryRssThreshold.nil? && !memoryRssThreshold.empty? memoryRssThresholdFloat = (memoryRssThreshold.to_f).round(2) metric_threshold_hash[Constants::MEMORY_RSS_BYTES] = memoryRssThresholdFloat end - memoryWorkingSetThreshold = Test_registry.instance.env["AZMON_ALERT_CONTAINER_MEMORY_WORKING_SET_THRESHOLD"] + memoryWorkingSetThreshold = env["AZMON_ALERT_CONTAINER_MEMORY_WORKING_SET_THRESHOLD"] if !memoryWorkingSetThreshold.nil? && !memoryWorkingSetThreshold.empty? memoryWorkingSetThresholdFloat = (memoryWorkingSetThreshold.to_f).round(2) metric_threshold_hash[Constants::MEMORY_WORKING_SET_BYTES] = memoryWorkingSetThresholdFloat end - pvUsagePercentageThreshold = Test_registry.instance.env["AZMON_ALERT_PV_USAGE_THRESHOLD"] + pvUsagePercentageThreshold = env["AZMON_ALERT_PV_USAGE_THRESHOLD"] if !pvUsagePercentageThreshold.nil? && !pvUsagePercentageThreshold.empty? pvUsagePercentageThresholdFloat = (pvUsagePercentageThreshold.to_f).round(2) metric_threshold_hash[Constants::PV_USED_BYTES] = pvUsagePercentageThresholdFloat end - jobCompletionTimeThreshold = Test_registry.instance.env["AZMON_ALERT_JOB_COMPLETION_TIME_THRESHOLD"] + jobCompletionTimeThreshold = env["AZMON_ALERT_JOB_COMPLETION_TIME_THRESHOLD"] if !jobCompletionTimeThreshold.nil? && !jobCompletionTimeThreshold.empty? jobCompletionTimeThresholdInt = jobCompletionTimeThreshold.to_i metric_threshold_hash[Constants::JOB_COMPLETION_TIME] = jobCompletionTimeThresholdInt diff --git a/source/plugins/ruby/filter_cadvisor2mdm.rb b/source/plugins/ruby/filter_cadvisor2mdm.rb index aadfd6db3..f3fe3e71e 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm.rb @@ -49,7 +49,7 @@ def configure(conf) end def start(env=ENV, applicationInsightsUtility=ApplicationInsightsUtility, kubernetesApiClient=KubernetesApiClient, kubeletUtils=KubeletUtils) - @ENV = env + @env = env @AplicationInsightsUtility = applicationInsightsUtility @KubernetesAPIClient = kubernetesApiClient @KubeletUtils = kubeletUtils @@ -57,13 +57,13 @@ def start(env=ENV, applicationInsightsUtility=ApplicationInsightsUtility, kubern super() @@isWindows = false - @@os_type = @ENV["OS_TYPE"] + @@os_type = @env["OS_TYPE"] if !@@os_type.nil? && !@@os_type.empty? && @@os_type.strip.casecmp("windows") == 0 @@isWindows = true end begin - @process_incoming_stream = CustomMetricsUtils.check_custom_metrics_availability(env=@ENV) + @process_incoming_stream = CustomMetricsUtils.check_custom_metrics_availability(env=@env) @metrics_to_collect_hash = build_metrics_hash(@metrics_to_collect) @Log.debug "After check_custom_metrics_availability process_incoming_stream #{@process_incoming_stream}" @@containerResourceUtilTelemetryTimeTracker = DateTime.now.to_time.to_i @@ -86,7 +86,7 @@ def start(env=ENV, applicationInsightsUtility=ApplicationInsightsUtility, kubern @containerMemoryLimitHash = {} @containerResourceDimensionHash = {} @pvUsageHash = {} - @@metric_threshold_hash = MdmMetricsGenerator.getContainerResourceUtilizationThresholds + @@metric_threshold_hash = MdmMetricsGenerator.getContainerResourceUtilizationThresholds(env=@env) @NodeCache = Fluent::Plugin::NodeStatsCache.new() end rescue => e @@ -343,7 +343,7 @@ def filterPVInsightsMetrics(record) end def ensure_cpu_memory_capacity_and_allocatable_set - @@controller_type = @ENV["CONTROLLER_TYPE"] + @@controller_type = @env["CONTROLLER_TYPE"] if @cpu_capacity != 0.0 && @memory_capacity != 0.0 && @@controller_type.downcase == "replicaset" @Log.info "CPU And Memory Capacity are already set and their values are as follows @cpu_capacity : #{@cpu_capacity}, @memory_capacity: #{@memory_capacity}" diff --git a/test/unit-tests/run_ruby_tests.sh b/test/unit-tests/run_ruby_tests.sh index 6896a2249..efc35890b 100755 --- a/test/unit-tests/run_ruby_tests.sh +++ b/test/unit-tests/run_ruby_tests.sh @@ -2,6 +2,6 @@ OLD_PATH=$(pwd) SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" cd $SCRIPTPATH/../../source/plugins/ruby -ruby filter_cadvisor2mdm_test.rb +ruby test_driver.rb cd $OLD_PATH From a5e230b918758f72a105caa3ade1398e3c460679 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Fri, 13 Aug 2021 18:13:06 -0700 Subject: [PATCH 17/33] go build broken --- source/plugins/go/src/go.mod | 11 +- source/plugins/go/src/go.sum | 492 +++++--------------------------- test/unit-tests/run_go_tests.sh | 1 + 3 files changed, 84 insertions(+), 420 deletions(-) diff --git a/source/plugins/go/src/go.mod b/source/plugins/go/src/go.mod index 24aac479a..f8e3db01a 100644 --- a/source/plugins/go/src/go.mod +++ b/source/plugins/go/src/go.mod @@ -3,10 +3,9 @@ module Docker-Provider/source/plugins/go/src go 1.14 require ( + code.cloudfoundry.org/clock v1.0.1-0.20200131002207-86534f4ca3a5 // indirect github.com/Azure/azure-kusto-go v0.3.2 github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 - github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect - github.com/dnaeon/go-vcr v1.2.0 // indirect github.com/fluent/fluent-bit-go v0.0.0-20171103221316-c4a158a6e3a7 github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680 // indirect github.com/gogo/protobuf v0.0.0-20170330071051-c0656edd0d9e // indirect @@ -14,12 +13,16 @@ require ( github.com/golang/mock v1.6.0 github.com/google/btree v0.0.0-20160524151835-7d79101e329e // indirect github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367 // indirect + github.com/google/uuid v1.1.1 github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d // indirect github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 // indirect github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3 // indirect - github.com/google/uuid v1.1.2 github.com/microsoft/ApplicationInsights-Go v0.4.3 - github.com/philhofer/fwd v1.1.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da // indirect + github.com/peterbourgon/diskv v2.0.1+incompatible // indirect + github.com/philhofer/fwd v1.0.0 // indirect + github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b // indirect github.com/tinylib/msgp v1.1.2 github.com/ugorji/go v1.1.2-0.20180813092308-00b869d2f4a5 golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f diff --git a/source/plugins/go/src/go.sum b/source/plugins/go/src/go.sum index 7f93bb260..9b6d5dd7a 100644 --- a/source/plugins/go/src/go.sum +++ b/source/plugins/go/src/go.sum @@ -1,28 +1,10 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c h1:5eeuG0BHx1+DHeT3AP+ISKZ2ht1UjGhm581ljqYpVeQ= code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +code.cloudfoundry.org/clock v1.0.1-0.20200131002207-86534f4ca3a5 h1:LTlZ2AD8IV/d1JRzB+HHfZfF1M+K8lyOlN28zDEpw7U= +code.cloudfoundry.org/clock v1.0.1-0.20200131002207-86534f4ca3a5/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= +github.com/Azure/azure-kusto-go v0.1.3 h1:0u+YqfIvwj5PHd+moXwtlxVePt8xTLU1ixM8Q6PjJ3o= +github.com/Azure/azure-kusto-go v0.1.3/go.mod h1:55hwXJ3PaahmWZFP7VC4+PlgsSUuetSA30rFtYFabfc= +github.com/Azure/azure-kusto-go v0.1.4-0.20200427191510-041d4ed55f86 h1:vyhCediIKg1gZ9H/kMcutU8F8BFNhxLk76Gti8UAOzo= +github.com/Azure/azure-kusto-go v0.1.4-0.20200427191510-041d4ed55f86/go.mod h1:55hwXJ3PaahmWZFP7VC4+PlgsSUuetSA30rFtYFabfc= github.com/Azure/azure-kusto-go v0.3.2 h1:XpS9co6GvEDl2oICF9HsjEsQVwEpRK6wbNWb9Z+uqsY= github.com/Azure/azure-kusto-go v0.3.2/go.mod h1:wd50n4qlsSxh+G4f80t+Fnl2ShK9AcXD+lMOstiKuYo= github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg= @@ -34,21 +16,18 @@ github.com/Azure/azure-storage-blob-go v0.8.0 h1:53qhf0Oxa0nOjgbDeeYPUeyiNmafAFE github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd h1:b3wyxBl3vvr15tUAziPBPK354y+LSdfPCpex5oBttHo= github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd/go.mod h1:K6am8mT+5iFXgingS9LUc7TmbsW6XBw3nxaRyaMyWc8= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v1.1.1 h1:4G9tVCqooRY3vDTB2bA1Z01PlSALtnUbji0AfzthUSs= +github.com/Azure/go-autorest v14.1.1+incompatible h1:m2F62e1Zk5DV3HENGdH/wEuzvJZIynHG4fHF7oiQwgE= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= github.com/Azure/go-autorest/autorest v0.10.0 h1:mvdtztBqcL8se7MdrUweNieTNi4kfNG6GOJuurQJpuY= github.com/Azure/go-autorest/autorest v0.10.0/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= -github.com/Azure/go-autorest/autorest v0.11.12 h1:gI8ytXbxMfI+IVbI9mP2JGCTXIuhHLgRlvQ9X4PsnHE= -github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= +github.com/Azure/go-autorest/autorest v0.10.2 h1:NuSF3gXetiHyUbVdneJMEVyPUYAe5wh+aN08JYAf1tI= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/adal v0.8.2 h1:O1X4oexUxnZCaEUGsvMnr8ZGj8HI37tNezwY4npRqA0= github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= -github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 h1:iM6UAvjR97ZIeR93qTcwpKNMpV+/FTWjwEbuPD495Tk= github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM= github.com/Azure/go-autorest/autorest/azure/cli v0.3.1 h1:LXl088ZQlP0SBppGFsRZonW6hSvwgL5gRByMbvUbx8U= @@ -56,471 +35,152 @@ github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9 github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/Microsoft/ApplicationInsights-Go v0.4.2 h1:HIZoGXMiKNwAtMAgCSSX35j9mP+DjGF9ezfBvxMDLLg= +github.com/Microsoft/ApplicationInsights-Go v0.4.2/go.mod h1:CukZ/G66zxXtI+h/VcVn3eVVDGDHfXM2zVILF7bMmsg= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= -github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fluent/fluent-bit-go v0.0.0-20171103221316-c4a158a6e3a7 h1:mck6KdLX2FTh2/ZD27dK69ehWDZR4hCk+nLf+HvAbDk= github.com/fluent/fluent-bit-go v0.0.0-20171103221316-c4a158a6e3a7/go.mod h1:JVF1Nl3QOPpKTR8xDjhkm0xINYUX0z4XdJvOpIUF+Eo= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= -github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680 h1:ZktWZesgun21uEDrwW7iEV1zPCGQldM2atlJZ3TdvVM= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gogo/protobuf v0.0.0-20170330071051-c0656edd0d9e h1:ago6fNuQ6IhszPsXkeU7qRCyfsIX7L67WDybsAPkLl8= +github.com/gogo/protobuf v0.0.0-20170330071051-c0656edd0d9e/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/glog v0.0.0-20141105023935-44145f04b68c h1:CbdkBQ1/PiAo0FYJhQGwASD8wrgNvTdf01g6+O9tNuA= +github.com/golang/glog v0.0.0-20141105023935-44145f04b68c/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/btree v0.0.0-20160524151835-7d79101e329e h1:JHB7F/4TJCrYBW8+GZO8VkWDj1jxcWuCl6uxKODiyi4= +github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367 h1:ScAXWS+TR6MZKex+7Z8rneuSJH+FSDqd6ocQyl+ZHo4= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k= +github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 h1:6TSoaYExHper8PYsJu23GWVNOyYRCSnIFyxKgLSZ54w= +github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3 h1:/UewZcckqhvnnS0C6r3Sher2hSEbVmM6Ogpcjen08+Y= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 h1:HfxbT6/JcvIljmERptWhwa8XzP7H3T+Z2N26gTsaDaA= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/microsoft/ApplicationInsights-Go v0.4.2 h1:LCv4NtCpXpsUF6ZUzZdpVG2x4RwebY7tiJUb25uYXiM= +github.com/microsoft/ApplicationInsights-Go v0.4.2/go.mod h1:DupRHRNoeuH4j8Yv3nux9/IXo3HZ0kO5A1ykNK4vR2E= github.com/microsoft/ApplicationInsights-Go v0.4.3 h1:gBuy5rM3o6Zo69QTkq1Ens8wx6sVf+mpgMjjfayiRcw= github.com/microsoft/ApplicationInsights-Go v0.4.3/go.mod h1:ih0t3h84PdzV1qGeUs89o9wL8eCuwf24M7TZp/nyqXk= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da h1:ZQGIPjr1iTtUPXZFk8WShqb5G+Qg65VHFLtSvmHh+Mw= +github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= -github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= +github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc h1:LUUe4cdABGrIJAhl1P1ZpWY76AwukVszFdwkVFVLwIk= +github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b h1:gQZ0qzfKHQIybLANtM3mBXNUtOfsCFXeTsnBqCsx1KM= +github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0= github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/ugorji/go v1.1.2-0.20180813092308-00b869d2f4a5 h1:JRe7Bc0YQq+x7Bm3p/LIBIb4aopsdr3H0KRKRI8g6oY= github.com/ugorji/go v1.1.2-0.20180813092308-00b869d2f4a5/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20180222182404-49796115aa4b h1:/GxqO8gbyb+sNnviFY2IIMrtm8vGg6NEJDft68wJY/g= +golang.org/x/crypto v0.0.0-20180222182404-49796115aa4b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo= +golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f h1:aZp0e2vLN4MToVqnjNEYEtrEA8RH8U8FN1CU7JgqsPU= +golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20170809000501-1c05540f6879 h1:0rFa7EaCGdQPmZVbo9F7MNF65b8dyzS6EUnXjs9Cllk= +golang.org/x/net v0.0.0-20170809000501-1c05540f6879/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 h1:OgUuv8lsRpBibGNbSizVwKWlysjaNzmC9gYMhPVfqFM= -golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20171031081856-95c657629925 h1:nCH33NboKIsT4HoXBsXTWX8ul303HxWgkc5s2Ezwacg= +golang.org/x/sys v0.0.0-20171031081856-95c657629925/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 h1:8qxJSnu+7dRq6upnbntrmriWByIakBuct5OM/MdQC1M= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.0.0-20170810154203-b19bf474d317 h1:WKW+OPdYPlvOTVGHuMfjnIC6yY2SI93yFB0pZ7giBmQ= +golang.org/x/text v0.0.0-20170810154203-b19bf474d317/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wktg7Jn/a/fNmr33HSj8g= +golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o= +gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3 h1:AFxeG48hTWHhDTQDk/m2gorfVHUEa9vo3tp3D7TzwjI= gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170721113624-670d4cfef054 h1:ROF+R/wHHruzF40n5DfPv2jwm7rCJwvs8fz+RTZWjLE= +gopkg.in/yaml.v2 v2.0.0-20170721113624-670d4cfef054/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.21.0 h1:gu5iGF4V6tfVCQ/R+8Hc0h7H1JuEhzyEi9S4R5LM8+Y= -k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= -k8s.io/apimachinery v0.21.0 h1:3Fx+41if+IRavNcKOz09FwEXDBG6ORh6iMsTSelhkMA= -k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= -k8s.io/client-go v0.21.0 h1:n0zzzJsAQmJngpC0IhgFcApZyoGXPrDIAD601HD09ag= -k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.8.0 h1:Q3gmuM9hKEjefWFFYF0Mat+YyFJvsUyYuwyNNJ5C9Ts= -k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.0 h1:C4r9BgJ98vrKnnVCjwCSXcWjWe0NKcUQkmzDXZXGwH8= -sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +k8s.io/api v0.0.0-20180628040859-072894a440bd h1:HzgYeLDS1jLxw8DGr68KJh9cdQ5iZJizG0HZWstIhfQ= +k8s.io/api v0.0.0-20180628040859-072894a440bd/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d h1:MZjlsu9igBoVPZkXpIGoxI6EonqNsXXZU7hhvfQLkd4= +k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/client-go v8.0.0+incompatible h1:tTI4hRmb1DRMl4fG6Vclfdi6nTM82oIrTT7HfitmxC4= +k8s.io/client-go v8.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= diff --git a/test/unit-tests/run_go_tests.sh b/test/unit-tests/run_go_tests.sh index d8649bd33..68fd56a69 100755 --- a/test/unit-tests/run_go_tests.sh +++ b/test/unit-tests/run_go_tests.sh @@ -1,3 +1,4 @@ +set -e OLD_PATH=$(pwd) SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" From 1078d461bfb57a982c1d781e98d4287a9e0fb096 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Fri, 13 Aug 2021 18:46:05 -0700 Subject: [PATCH 18/33] fixed go build --- source/plugins/go/src/go.mod | 29 +-- source/plugins/go/src/go.sum | 493 +++++++++++++++++++++++++++++------ 2 files changed, 424 insertions(+), 98 deletions(-) diff --git a/source/plugins/go/src/go.mod b/source/plugins/go/src/go.mod index f8e3db01a..58e668597 100644 --- a/source/plugins/go/src/go.mod +++ b/source/plugins/go/src/go.mod @@ -3,33 +3,18 @@ module Docker-Provider/source/plugins/go/src go 1.14 require ( - code.cloudfoundry.org/clock v1.0.1-0.20200131002207-86534f4ca3a5 // indirect github.com/Azure/azure-kusto-go v0.3.2 github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 + github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect + github.com/dnaeon/go-vcr v1.2.0 // indirect github.com/fluent/fluent-bit-go v0.0.0-20171103221316-c4a158a6e3a7 - github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680 // indirect - github.com/gogo/protobuf v0.0.0-20170330071051-c0656edd0d9e // indirect - github.com/golang/glog v0.0.0-20141105023935-44145f04b68c // indirect - github.com/golang/mock v1.6.0 - github.com/google/btree v0.0.0-20160524151835-7d79101e329e // indirect - github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367 // indirect - github.com/google/uuid v1.1.1 - github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d // indirect - github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 // indirect - github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3 // indirect + github.com/golang/mock v1.4.1 + github.com/google/uuid v1.1.2 github.com/microsoft/ApplicationInsights-Go v0.4.3 - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da // indirect - github.com/peterbourgon/diskv v2.0.1+incompatible // indirect - github.com/philhofer/fwd v1.0.0 // indirect - github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b // indirect + github.com/philhofer/fwd v1.1.1 // indirect github.com/tinylib/msgp v1.1.2 github.com/ugorji/go v1.1.2-0.20180813092308-00b869d2f4a5 - golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f - golang.org/x/time v0.0.0-20161028155119-f51c12702a4d // indirect - gopkg.in/inf.v0 v0.9.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3 - k8s.io/api v0.0.0-20180628040859-072894a440bd // indirect - k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d - k8s.io/client-go v8.0.0+incompatible + k8s.io/apimachinery v0.21.0 + k8s.io/client-go v0.21.0 ) diff --git a/source/plugins/go/src/go.sum b/source/plugins/go/src/go.sum index 9b6d5dd7a..ad9e40089 100644 --- a/source/plugins/go/src/go.sum +++ b/source/plugins/go/src/go.sum @@ -1,10 +1,28 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c h1:5eeuG0BHx1+DHeT3AP+ISKZ2ht1UjGhm581ljqYpVeQ= code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= -code.cloudfoundry.org/clock v1.0.1-0.20200131002207-86534f4ca3a5 h1:LTlZ2AD8IV/d1JRzB+HHfZfF1M+K8lyOlN28zDEpw7U= -code.cloudfoundry.org/clock v1.0.1-0.20200131002207-86534f4ca3a5/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= -github.com/Azure/azure-kusto-go v0.1.3 h1:0u+YqfIvwj5PHd+moXwtlxVePt8xTLU1ixM8Q6PjJ3o= -github.com/Azure/azure-kusto-go v0.1.3/go.mod h1:55hwXJ3PaahmWZFP7VC4+PlgsSUuetSA30rFtYFabfc= -github.com/Azure/azure-kusto-go v0.1.4-0.20200427191510-041d4ed55f86 h1:vyhCediIKg1gZ9H/kMcutU8F8BFNhxLk76Gti8UAOzo= -github.com/Azure/azure-kusto-go v0.1.4-0.20200427191510-041d4ed55f86/go.mod h1:55hwXJ3PaahmWZFP7VC4+PlgsSUuetSA30rFtYFabfc= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-kusto-go v0.3.2 h1:XpS9co6GvEDl2oICF9HsjEsQVwEpRK6wbNWb9Z+uqsY= github.com/Azure/azure-kusto-go v0.3.2/go.mod h1:wd50n4qlsSxh+G4f80t+Fnl2ShK9AcXD+lMOstiKuYo= github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg= @@ -16,18 +34,21 @@ github.com/Azure/azure-storage-blob-go v0.8.0 h1:53qhf0Oxa0nOjgbDeeYPUeyiNmafAFE github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd h1:b3wyxBl3vvr15tUAziPBPK354y+LSdfPCpex5oBttHo= github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd/go.mod h1:K6am8mT+5iFXgingS9LUc7TmbsW6XBw3nxaRyaMyWc8= -github.com/Azure/go-autorest v1.1.1 h1:4G9tVCqooRY3vDTB2bA1Z01PlSALtnUbji0AfzthUSs= -github.com/Azure/go-autorest v14.1.1+incompatible h1:m2F62e1Zk5DV3HENGdH/wEuzvJZIynHG4fHF7oiQwgE= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= github.com/Azure/go-autorest/autorest v0.10.0 h1:mvdtztBqcL8se7MdrUweNieTNi4kfNG6GOJuurQJpuY= github.com/Azure/go-autorest/autorest v0.10.0/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= -github.com/Azure/go-autorest/autorest v0.10.2 h1:NuSF3gXetiHyUbVdneJMEVyPUYAe5wh+aN08JYAf1tI= +github.com/Azure/go-autorest/autorest v0.11.12 h1:gI8ytXbxMfI+IVbI9mP2JGCTXIuhHLgRlvQ9X4PsnHE= +github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/adal v0.8.2 h1:O1X4oexUxnZCaEUGsvMnr8ZGj8HI37tNezwY4npRqA0= github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 h1:iM6UAvjR97ZIeR93qTcwpKNMpV+/FTWjwEbuPD495Tk= github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM= github.com/Azure/go-autorest/autorest/azure/cli v0.3.1 h1:LXl088ZQlP0SBppGFsRZonW6hSvwgL5gRByMbvUbx8U= @@ -35,152 +56,472 @@ github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9 github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= +github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/Microsoft/ApplicationInsights-Go v0.4.2 h1:HIZoGXMiKNwAtMAgCSSX35j9mP+DjGF9ezfBvxMDLLg= -github.com/Microsoft/ApplicationInsights-Go v0.4.2/go.mod h1:CukZ/G66zxXtI+h/VcVn3eVVDGDHfXM2zVILF7bMmsg= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fluent/fluent-bit-go v0.0.0-20171103221316-c4a158a6e3a7 h1:mck6KdLX2FTh2/ZD27dK69ehWDZR4hCk+nLf+HvAbDk= github.com/fluent/fluent-bit-go v0.0.0-20171103221316-c4a158a6e3a7/go.mod h1:JVF1Nl3QOPpKTR8xDjhkm0xINYUX0z4XdJvOpIUF+Eo= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680 h1:ZktWZesgun21uEDrwW7iEV1zPCGQldM2atlJZ3TdvVM= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gogo/protobuf v0.0.0-20170330071051-c0656edd0d9e h1:ago6fNuQ6IhszPsXkeU7qRCyfsIX7L67WDybsAPkLl8= -github.com/gogo/protobuf v0.0.0-20170330071051-c0656edd0d9e/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/glog v0.0.0-20141105023935-44145f04b68c h1:CbdkBQ1/PiAo0FYJhQGwASD8wrgNvTdf01g6+O9tNuA= -github.com/golang/glog v0.0.0-20141105023935-44145f04b68c/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc= -github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1 h1:ocYkMQY5RrXTYgXl7ICpV0IXwlEQGwKIsery4gyXa1U= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/google/btree v0.0.0-20160524151835-7d79101e329e h1:JHB7F/4TJCrYBW8+GZO8VkWDj1jxcWuCl6uxKODiyi4= -github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367 h1:ScAXWS+TR6MZKex+7Z8rneuSJH+FSDqd6ocQyl+ZHo4= -github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k= -github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 h1:6TSoaYExHper8PYsJu23GWVNOyYRCSnIFyxKgLSZ54w= -github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3 h1:/UewZcckqhvnnS0C6r3Sher2hSEbVmM6Ogpcjen08+Y= -github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 h1:HfxbT6/JcvIljmERptWhwa8XzP7H3T+Z2N26gTsaDaA= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= -github.com/microsoft/ApplicationInsights-Go v0.4.2 h1:LCv4NtCpXpsUF6ZUzZdpVG2x4RwebY7tiJUb25uYXiM= -github.com/microsoft/ApplicationInsights-Go v0.4.2/go.mod h1:DupRHRNoeuH4j8Yv3nux9/IXo3HZ0kO5A1ykNK4vR2E= github.com/microsoft/ApplicationInsights-Go v0.4.3 h1:gBuy5rM3o6Zo69QTkq1Ens8wx6sVf+mpgMjjfayiRcw= github.com/microsoft/ApplicationInsights-Go v0.4.3/go.mod h1:ih0t3h84PdzV1qGeUs89o9wL8eCuwf24M7TZp/nyqXk= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da h1:ZQGIPjr1iTtUPXZFk8WShqb5G+Qg65VHFLtSvmHh+Mw= -github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= -github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= +github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b h1:gQZ0qzfKHQIybLANtM3mBXNUtOfsCFXeTsnBqCsx1KM= -github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc h1:LUUe4cdABGrIJAhl1P1ZpWY76AwukVszFdwkVFVLwIk= github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0= github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/ugorji/go v1.1.2-0.20180813092308-00b869d2f4a5 h1:JRe7Bc0YQq+x7Bm3p/LIBIb4aopsdr3H0KRKRI8g6oY= github.com/ugorji/go v1.1.2-0.20180813092308-00b869d2f4a5/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -golang.org/x/crypto v0.0.0-20180222182404-49796115aa4b h1:/GxqO8gbyb+sNnviFY2IIMrtm8vGg6NEJDft68wJY/g= -golang.org/x/crypto v0.0.0-20180222182404-49796115aa4b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo= -golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f h1:aZp0e2vLN4MToVqnjNEYEtrEA8RH8U8FN1CU7JgqsPU= -golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20170809000501-1c05540f6879 h1:0rFa7EaCGdQPmZVbo9F7MNF65b8dyzS6EUnXjs9Cllk= -golang.org/x/net v0.0.0-20170809000501-1c05540f6879/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI= -golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 h1:OgUuv8lsRpBibGNbSizVwKWlysjaNzmC9gYMhPVfqFM= +golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20171031081856-95c657629925 h1:nCH33NboKIsT4HoXBsXTWX8ul303HxWgkc5s2Ezwacg= -golang.org/x/sys v0.0.0-20171031081856-95c657629925/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 h1:8qxJSnu+7dRq6upnbntrmriWByIakBuct5OM/MdQC1M= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170810154203-b19bf474d317 h1:WKW+OPdYPlvOTVGHuMfjnIC6yY2SI93yFB0pZ7giBmQ= -golang.org/x/text v0.0.0-20170810154203-b19bf474d317/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wktg7Jn/a/fNmr33HSj8g= -golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o= -gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3 h1:AFxeG48hTWHhDTQDk/m2gorfVHUEa9vo3tp3D7TzwjI= gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170721113624-670d4cfef054 h1:ROF+R/wHHruzF40n5DfPv2jwm7rCJwvs8fz+RTZWjLE= -gopkg.in/yaml.v2 v2.0.0-20170721113624-670d4cfef054/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -k8s.io/api v0.0.0-20180628040859-072894a440bd h1:HzgYeLDS1jLxw8DGr68KJh9cdQ5iZJizG0HZWstIhfQ= -k8s.io/api v0.0.0-20180628040859-072894a440bd/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= -k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d h1:MZjlsu9igBoVPZkXpIGoxI6EonqNsXXZU7hhvfQLkd4= -k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= -k8s.io/client-go v8.0.0+incompatible h1:tTI4hRmb1DRMl4fG6Vclfdi6nTM82oIrTT7HfitmxC4= -k8s.io/client-go v8.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.21.0 h1:gu5iGF4V6tfVCQ/R+8Hc0h7H1JuEhzyEi9S4R5LM8+Y= +k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= +k8s.io/apimachinery v0.21.0 h1:3Fx+41if+IRavNcKOz09FwEXDBG6ORh6iMsTSelhkMA= +k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= +k8s.io/client-go v0.21.0 h1:n0zzzJsAQmJngpC0IhgFcApZyoGXPrDIAD601HD09ag= +k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.8.0 h1:Q3gmuM9hKEjefWFFYF0Mat+YyFJvsUyYuwyNNJ5C9Ts= +k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.0 h1:C4r9BgJ98vrKnnVCjwCSXcWjWe0NKcUQkmzDXZXGwH8= +sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= From aed8cc4f08544b484015e2166f9a6b5e176cd724 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Tue, 17 Aug 2021 15:28:31 -0700 Subject: [PATCH 19/33] basic in_kube_nodes test --- .../installer/datafiles/base_container.data | 1 - .../plugins/ruby/filter_cadvisor2mdm_test.rb | 72 +- source/plugins/ruby/in_kube_nodes.rb | 110 ++- source/plugins/ruby/in_kube_nodes_test.rb | 147 +++ source/plugins/ruby/test_driver.rb | 6 + .../kube-nodes-malformed.txt | 832 +++++++++++++++++ .../canned-api-responses/kube-nodes.txt | 851 ++++++++++++++++++ 7 files changed, 1939 insertions(+), 80 deletions(-) create mode 100644 source/plugins/ruby/in_kube_nodes_test.rb create mode 100644 source/plugins/ruby/test_driver.rb create mode 100644 test/unit-tests/canned-api-responses/kube-nodes-malformed.txt create mode 100644 test/unit-tests/canned-api-responses/kube-nodes.txt diff --git a/build/linux/installer/datafiles/base_container.data b/build/linux/installer/datafiles/base_container.data index 152a7f47a..d104a5084 100644 --- a/build/linux/installer/datafiles/base_container.data +++ b/build/linux/installer/datafiles/base_container.data @@ -172,7 +172,6 @@ MAINTAINER: 'Microsoft Corporation' /etc/fluent/plugin/filter_cadvisor_health_container.rb; source/plugins/ruby/filter_cadvisor_health_container.rb; 644; root; root /etc/fluent/plugin/filter_cadvisor_health_node.rb; source/plugins/ruby/filter_cadvisor_health_node.rb; 644; root; root /etc/fluent/plugin/filter_cadvisor2mdm.rb; source/plugins/ruby/filter_cadvisor2mdm.rb; 644; root; root -/etc/fluent/plugin/filter_cadvisor2mdm_test.rb; source/plugins/ruby/filter_cadvisor2mdm_test.rb; 644; root; root /etc/fluent/plugin/filter_health_model_builder.rb; source/plugins/ruby/filter_health_model_builder.rb; 644; root; root /etc/fluent/plugin/filter_inventory2mdm.rb; source/plugins/ruby/filter_inventory2mdm.rb; 644; root; root /etc/fluent/plugin/filter_telegraf2mdm.rb; source/plugins/ruby/filter_telegraf2mdm.rb; 644; root; root diff --git a/source/plugins/ruby/filter_cadvisor2mdm_test.rb b/source/plugins/ruby/filter_cadvisor2mdm_test.rb index 58a3a8801..d3e398989 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm_test.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm_test.rb @@ -1,7 +1,10 @@ # TODO: can we get rid of this global flag $in_unit_test = true -require "test-unit" +# TODO: get rid of require test-unit if we switch to minitest +# require "test-unit" +require 'minitest/autorun' +# require 'fluent/test' require 'fluent/test/driver/filter' require 'fluent/test/helpers' @@ -10,10 +13,41 @@ require 'byebug' -class MyInputTest < Test::Unit::TestCase +class Ai_utility_stub + class << self + def sendCustomEvent(a, b) + end + + def sendExceptionTelemetry (errorstr) + # this shouldn't happen, why was there an exception? + byebug + end + end +end + +class KubernetesApiClientMock < KubernetesApiClient + class GetNodesResponse + def body + return "{\"kind\":\"NodeList\",\"apiVersion\":\"v1\",\"metadata\":{\"selfLink\":\"/api/v1/nodes\",\"resourceVersion\":\"4597672\"},\"items\":[{\"metadata\":{\"name\":\"aks-nodepool1-24816391-vmss000000\",\"selfLink\":\"/api/v1/nodes/aks-nodepool1-24816391-vmss000000\",\"uid\":\"fe073f0a-e6bf-4d68-b4e5-ffaa42b91528\",\"resourceVersion\":\"4597521\",\"creationTimestamp\":\"2021-07-21T23:40:14Z\",\"labels\":{\"agentpool\":\"nodepool1\",\"beta.kubernetes.io/arch\":\"amd64\",\"beta.kubernetes.io/instance-type\":\"Standard_DS2_v2\",\"beta.kubernetes.io/os\":\"linux\",\"failure-domain.beta.kubernetes.io/region\":\"westus2\",\"failure-domain.beta.kubernetes.io/zone\":\"0\",\"kubernetes.azure.com/cluster\":\"MC_davidaks16_davidaks16_westus2\",\"kubernetes.azure.com/mode\":\"system\",\"kubernetes.azure.com/node-image-version\":\"AKSUbuntu-1804gen2containerd-2021.07.03\",\"kubernetes.azure.com/os-sku\":\"Ubuntu\",\"kubernetes.azure.com/role\":\"agent\",\"kubernetes.io/arch\":\"amd64\",\"kubernetes.io/hostname\":\"aks-nodepool1-24816391-vmss000000\",\"kubernetes.io/os\":\"linux\",\"kubernetes.io/role\":\"agent\",\"node-role.kubernetes.io/agent\":\"\",\"node.kubernetes.io/instance-type\":\"Standard_DS2_v2\",\"storageprofile\":\"managed\",\"storagetier\":\"Premium_LRS\",\"topology.kubernetes.io/region\":\"westus2\",\"topology.kubernetes.io/zone\":\"0\"},\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"0\",\"volumes.kubernetes.io/controller-managed-attach-detach\":\"true\"},\"managedFields\":[{\"manager\":\"kube-controller-manager\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-07-21T23:40:20Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:metadata\":{\"f:annotations\":{\"f:node.alpha.kubernetes.io/ttl\":{}}}}},{\"manager\":\"kubelet\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-07-21T23:40:24Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:metadata\":{\"f:annotations\":{\".\":{},\"f:volumes.kubernetes.io/controller-managed-attach-detach\":{}},\"f:labels\":{\".\":{},\"f:agentpool\":{},\"f:beta.kubernetes.io/arch\":{},\"f:beta.kubernetes.io/instance-type\":{},\"f:beta.kubernetes.io/os\":{},\"f:failure-domain.beta.kubernetes.io/region\":{},\"f:failure-domain.beta.kubernetes.io/zone\":{},\"f:kubernetes.azure.com/cluster\":{},\"f:kubernetes.azure.com/mode\":{},\"f:kubernetes.azure.com/node-image-version\":{},\"f:kubernetes.azure.com/os-sku\":{},\"f:kubernetes.azure.com/role\":{},\"f:kubernetes.io/arch\":{},\"f:kubernetes.io/hostname\":{},\"f:kubernetes.io/os\":{},\"f:node.kubernetes.io/instance-type\":{},\"f:storageprofile\":{},\"f:storagetier\":{},\"f:topology.kubernetes.io/region\":{},\"f:topology.kubernetes.io/zone\":{}}},\"f:spec\":{\"f:providerID\":{}},\"f:status\":{\"f:addresses\":{\".\":{},\"k:{\\\"type\\\":\\\"Hostname\\\"}\":{\".\":{},\"f:address\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"InternalIP\\\"}\":{\".\":{},\"f:address\":{},\"f:type\":{}}},\"f:allocatable\":{\".\":{},\"f:attachable-volumes-azure-disk\":{},\"f:cpu\":{},\"f:ephemeral-storage\":{},\"f:hugepages-1Gi\":{},\"f:hugepages-2Mi\":{},\"f:memory\":{},\"f:pods\":{}},\"f:capacity\":{\".\":{},\"f:attachable-volumes-azure-disk\":{},\"f:cpu\":{},\"f:ephemeral-storage\":{},\"f:hugepages-1Gi\":{},\"f:hugepages-2Mi\":{},\"f:memory\":{},\"f:pods\":{}},\"f:conditions\":{\".\":{},\"k:{\\\"type\\\":\\\"DiskPressure\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"MemoryPressure\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"PIDPressure\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"Ready\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}}},\"f:config\":{},\"f:daemonEndpoints\":{\"f:kubeletEndpoint\":{\"f:Port\":{}}},\"f:images\":{},\"f:nodeInfo\":{\"f:architecture\":{},\"f:bootID\":{},\"f:containerRuntimeVersion\":{},\"f:kernelVersion\":{},\"f:kubeProxyVersion\":{},\"f:kubeletVersion\":{},\"f:machineID\":{},\"f:operatingSystem\":{},\"f:osImage\":{},\"f:systemUUID\":{}}}}},{\"manager\":\"kubectl-label\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-07-21T23:40:53Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:metadata\":{\"f:labels\":{\"f:kubernetes.io/role\":{},\"f:node-role.kubernetes.io/agent\":{}}}}},{\"manager\":\"node-problem-detector\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-08-10T18:10:02Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:status\":{\"f:conditions\":{\"k:{\\\"type\\\":\\\"ContainerRuntimeProblem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FilesystemCorruptionProblem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FreezeScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentContainerdRestart\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentDockerRestart\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentKubeletRestart\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentUnregisterNetDevice\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"KernelDeadlock\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"KubeletProblem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"PreemptScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"ReadonlyFilesystem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"RebootScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"RedeployScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"TerminateScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}}}}}}]},\"spec\":{\"providerID\":\"azure:///subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/mc_davidaks16_davidaks16_westus2/providers/Microsoft.Compute/virtualMachineScaleSets/aks-nodepool1-24816391-vmss/virtualMachines/0\"},\"status\":{\"capacity\":{\"attachable-volumes-azure-disk\":\"8\",\"cpu\":\"2\",\"ephemeral-storage\":\"129900528Ki\",\"hugepages-1Gi\":\"0\",\"hugepages-2Mi\":\"0\",\"memory\":\"7120616Ki\",\"pods\":\"30\"},\"allocatable\":{\"attachable-volumes-azure-disk\":\"8\",\"cpu\":\"1900m\",\"ephemeral-storage\":\"119716326407\",\"hugepages-1Gi\":\"0\",\"hugepages-2Mi\":\"0\",\"memory\":\"4675304Ki\",\"pods\":\"30\"},\"conditions\":[{\"type\":\"FrequentContainerdRestart\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentContainerdRestart\",\"message\":\"containerd is functioning properly\"},{\"type\":\"FreezeScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFreezeScheduled\",\"message\":\"VM has no scheduled Freeze event\"},{\"type\":\"FrequentDockerRestart\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentDockerRestart\",\"message\":\"docker is functioning properly\"},{\"type\":\"FilesystemCorruptionProblem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"FilesystemIsOK\",\"message\":\"Filesystem is healthy\"},{\"type\":\"KernelDeadlock\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"KernelHasNoDeadlock\",\"message\":\"kernel has no deadlock\"},{\"type\":\"TerminateScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoTerminateScheduled\",\"message\":\"VM has no scheduled Terminate event\"},{\"type\":\"ReadonlyFilesystem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"FilesystemIsNotReadOnly\",\"message\":\"Filesystem is not read-only\"},{\"type\":\"FrequentUnregisterNetDevice\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentUnregisterNetDevice\",\"message\":\"node is functioning properly\"},{\"type\":\"KubeletProblem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"KubeletIsUp\",\"message\":\"kubelet service is up\"},{\"type\":\"PreemptScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:11:11Z\",\"reason\":\"NoPreemptScheduled\",\"message\":\"VM has no scheduled Preempt event\"},{\"type\":\"RedeployScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoRedeployScheduled\",\"message\":\"VM has no scheduled Redeploy event\"},{\"type\":\"ContainerRuntimeProblem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"ContainerRuntimeIsUp\",\"message\":\"container runtime service is up\"},{\"type\":\"FrequentKubeletRestart\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentKubeletRestart\",\"message\":\"kubelet is functioning properly\"},{\"type\":\"RebootScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoRebootScheduled\",\"message\":\"VM has no scheduled Reboot event\"},{\"type\":\"MemoryPressure\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:14Z\",\"reason\":\"KubeletHasSufficientMemory\",\"message\":\"kubelet has sufficient memory available\"},{\"type\":\"DiskPressure\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:14Z\",\"reason\":\"KubeletHasNoDiskPressure\",\"message\":\"kubelet has no disk pressure\"},{\"type\":\"PIDPressure\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:14Z\",\"reason\":\"KubeletHasSufficientPID\",\"message\":\"kubelet has sufficient PID available\"},{\"type\":\"Ready\",\"status\":\"True\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:24Z\",\"reason\":\"KubeletReady\",\"message\":\"kubelet is posting ready status. AppArmor enabled\"}],\"addresses\":[{\"type\":\"Hostname\",\"address\":\"aks-nodepool1-24816391-vmss000000\"},{\"type\":\"InternalIP\",\"address\":\"10.240.0.4\"}],\"daemonEndpoints\":{\"kubeletEndpoint\":{\"Port\":10250}},\"nodeInfo\":{\"machineID\":\"17a654260e2c4a9bb3a3eb4b4188e4b4\",\"systemUUID\":\"7ff599e4-909e-4950-a044-ff8613af3af9\",\"bootID\":\"02bb865b-a469-43cd-8b0b-5ceb4ecd80b0\",\"kernelVersion\":\"5.4.0-1051-azure\",\"osImage\":\"Ubuntu 18.04.5 LTS\",\"containerRuntimeVersion\":\"containerd://1.4.4+azure\",\"kubeletVersion\":\"v1.19.11\",\"kubeProxyVersion\":\"v1.19.11\",\"operatingSystem\":\"linux\",\"architecture\":\"amd64\"},\"images\":[{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021-1\"],\"sizeBytes\":331689060},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021\"],\"sizeBytes\":330099815},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021-hotfix\"],\"sizeBytes\":271471426},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021\"],\"sizeBytes\":269703297},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod03262021\"],\"sizeBytes\":264732875},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.19.0\"],\"sizeBytes\":166352383},{\"names\":[\"mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210623.2\"],\"sizeBytes\":147750148},{\"names\":[\"mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210524.1\"],\"sizeBytes\":146446618},{\"names\":[\"mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210427.1\"],\"sizeBytes\":136242776},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.8.9.5\"],\"sizeBytes\":101794833},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.47.0\"],\"sizeBytes\":101445696},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/autoscaler/cluster-proportional-autoscaler:1.3.0_v0.0.5\"],\"sizeBytes\":101194562},{\"names\":[\"mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210623.2\"],\"sizeBytes\":96125176},{\"names\":[\"mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210524.1\"],\"sizeBytes\":95879501},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/exechealthz:1.2_v0.0.5\"],\"sizeBytes\":94348102},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.8.9.2\"],\"sizeBytes\":93537927},{\"names\":[\"mcr.microsoft.com/aks/acc/sgx-attestation:2.0\"],\"sizeBytes\":91841669},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.4.0\"],\"sizeBytes\":91324193},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.2.0\"],\"sizeBytes\":89103171},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.0.1-rc3\"],\"sizeBytes\":86839805},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.2.0\"],\"sizeBytes\":86488586},{\"names\":[\"mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210427.1\"],\"sizeBytes\":86120048},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.3.0\"],\"sizeBytes\":81252495},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.4.0\"],\"sizeBytes\":79586703},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.4.0\"],\"sizeBytes\":78795016},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.2.0\"],\"sizeBytes\":76527179},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.1.8\"],\"sizeBytes\":75025803},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.2.2_hotfix\"],\"sizeBytes\":73533889},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.3.1\"],\"sizeBytes\":72242894},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.2.8\"],\"sizeBytes\":70622822},{\"names\":[\"mcr.microsoft.com/oss/nvidia/k8s-device-plugin:v0.9.0\"],\"sizeBytes\":67291599},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.1\"],\"sizeBytes\":66415836},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc7\"],\"sizeBytes\":65965658},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.2.1\"],\"sizeBytes\":64123775},{\"names\":[\"mcr.microsoft.com/oss/calico/cni:v3.8.9.3\"],\"sizeBytes\":63581323},{\"names\":[\"mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8\"],\"sizeBytes\":63154716},{\"names\":[\"mcr.microsoft.com/oss/calico/cni:v3.8.9.2\"],\"sizeBytes\":61626312},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.18.1\"],\"sizeBytes\":60500885},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.17.2\"],\"sizeBytes\":58419768},{\"names\":[\"mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8_hotfix\",\"mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8post2\"],\"sizeBytes\":56368756},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:282543237a1aa3f407656290f454b7068a92e1abe2156082c750d5abfbcad90c\",\"mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.2\"],\"sizeBytes\":56310724},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.19.0\"],\"sizeBytes\":55228749},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.1\"],\"sizeBytes\":54692048},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc3\"],\"sizeBytes\":50803639},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.19\"],\"sizeBytes\":49759361},{\"names\":[\"mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.5\"],\"sizeBytes\":49704644},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.21\"],\"sizeBytes\":49372390},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:a64d3538b72905b07356881314755b02db3675ff47ee2bcc49dd7be856e285d5\",\"mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526\"],\"sizeBytes\":49322942},{\"names\":[\"mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.4\"],\"sizeBytes\":48108311},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kubernetes-dashboard:v1.10.1\"],\"sizeBytes\":44907744}],\"config\":{}}}]}\n" + end + end + class << self + def getKubeResourceInfo(resource, api_group: nil) + if resource == "nodes?fieldSelector=metadata.name%3DWIN-T14B9CT7KMS" + return GetNodesResponse.new() + end + # this means that a saved input is missing + byebug + end + end +end + + + +class MyInputTest < Minitest::Test include Fluent::Test::Helpers - setup do + def setup Fluent::Test.setup end @@ -22,7 +56,7 @@ def create_driver(conf = "") end # A relatively simple test for a helper method - test "build_metrics_hash" do + def test_build_metrics_hash instance = create_driver.instance expected = {"constants::cpu_usage_nano_cores" => true, "constants::memory_working_set_bytes" => true, "constants::memory_rss_bytes"=> true, "constants::pv_used_bytes"=> true} @@ -37,36 +71,8 @@ def create_driver(conf = "") # a much more complicated test for the filter method of filter_cadvisor2mdm (this is an allup test) - test 'filter' do - - class Ai_utility_stub - class << self - def sendCustomEvent(a, b) - end - - def sendExceptionTelemetry (errorstr) - # this shouldn't happen, why was there an exception? - byebug - end - end - end + def test_filter - class KubernetesApiClientMock < KubernetesApiClient - class GetNodesResponse - def body - return "{\"kind\":\"NodeList\",\"apiVersion\":\"v1\",\"metadata\":{\"selfLink\":\"/api/v1/nodes\",\"resourceVersion\":\"4597672\"},\"items\":[{\"metadata\":{\"name\":\"aks-nodepool1-24816391-vmss000000\",\"selfLink\":\"/api/v1/nodes/aks-nodepool1-24816391-vmss000000\",\"uid\":\"fe073f0a-e6bf-4d68-b4e5-ffaa42b91528\",\"resourceVersion\":\"4597521\",\"creationTimestamp\":\"2021-07-21T23:40:14Z\",\"labels\":{\"agentpool\":\"nodepool1\",\"beta.kubernetes.io/arch\":\"amd64\",\"beta.kubernetes.io/instance-type\":\"Standard_DS2_v2\",\"beta.kubernetes.io/os\":\"linux\",\"failure-domain.beta.kubernetes.io/region\":\"westus2\",\"failure-domain.beta.kubernetes.io/zone\":\"0\",\"kubernetes.azure.com/cluster\":\"MC_davidaks16_davidaks16_westus2\",\"kubernetes.azure.com/mode\":\"system\",\"kubernetes.azure.com/node-image-version\":\"AKSUbuntu-1804gen2containerd-2021.07.03\",\"kubernetes.azure.com/os-sku\":\"Ubuntu\",\"kubernetes.azure.com/role\":\"agent\",\"kubernetes.io/arch\":\"amd64\",\"kubernetes.io/hostname\":\"aks-nodepool1-24816391-vmss000000\",\"kubernetes.io/os\":\"linux\",\"kubernetes.io/role\":\"agent\",\"node-role.kubernetes.io/agent\":\"\",\"node.kubernetes.io/instance-type\":\"Standard_DS2_v2\",\"storageprofile\":\"managed\",\"storagetier\":\"Premium_LRS\",\"topology.kubernetes.io/region\":\"westus2\",\"topology.kubernetes.io/zone\":\"0\"},\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"0\",\"volumes.kubernetes.io/controller-managed-attach-detach\":\"true\"},\"managedFields\":[{\"manager\":\"kube-controller-manager\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-07-21T23:40:20Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:metadata\":{\"f:annotations\":{\"f:node.alpha.kubernetes.io/ttl\":{}}}}},{\"manager\":\"kubelet\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-07-21T23:40:24Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:metadata\":{\"f:annotations\":{\".\":{},\"f:volumes.kubernetes.io/controller-managed-attach-detach\":{}},\"f:labels\":{\".\":{},\"f:agentpool\":{},\"f:beta.kubernetes.io/arch\":{},\"f:beta.kubernetes.io/instance-type\":{},\"f:beta.kubernetes.io/os\":{},\"f:failure-domain.beta.kubernetes.io/region\":{},\"f:failure-domain.beta.kubernetes.io/zone\":{},\"f:kubernetes.azure.com/cluster\":{},\"f:kubernetes.azure.com/mode\":{},\"f:kubernetes.azure.com/node-image-version\":{},\"f:kubernetes.azure.com/os-sku\":{},\"f:kubernetes.azure.com/role\":{},\"f:kubernetes.io/arch\":{},\"f:kubernetes.io/hostname\":{},\"f:kubernetes.io/os\":{},\"f:node.kubernetes.io/instance-type\":{},\"f:storageprofile\":{},\"f:storagetier\":{},\"f:topology.kubernetes.io/region\":{},\"f:topology.kubernetes.io/zone\":{}}},\"f:spec\":{\"f:providerID\":{}},\"f:status\":{\"f:addresses\":{\".\":{},\"k:{\\\"type\\\":\\\"Hostname\\\"}\":{\".\":{},\"f:address\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"InternalIP\\\"}\":{\".\":{},\"f:address\":{},\"f:type\":{}}},\"f:allocatable\":{\".\":{},\"f:attachable-volumes-azure-disk\":{},\"f:cpu\":{},\"f:ephemeral-storage\":{},\"f:hugepages-1Gi\":{},\"f:hugepages-2Mi\":{},\"f:memory\":{},\"f:pods\":{}},\"f:capacity\":{\".\":{},\"f:attachable-volumes-azure-disk\":{},\"f:cpu\":{},\"f:ephemeral-storage\":{},\"f:hugepages-1Gi\":{},\"f:hugepages-2Mi\":{},\"f:memory\":{},\"f:pods\":{}},\"f:conditions\":{\".\":{},\"k:{\\\"type\\\":\\\"DiskPressure\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"MemoryPressure\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"PIDPressure\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"Ready\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}}},\"f:config\":{},\"f:daemonEndpoints\":{\"f:kubeletEndpoint\":{\"f:Port\":{}}},\"f:images\":{},\"f:nodeInfo\":{\"f:architecture\":{},\"f:bootID\":{},\"f:containerRuntimeVersion\":{},\"f:kernelVersion\":{},\"f:kubeProxyVersion\":{},\"f:kubeletVersion\":{},\"f:machineID\":{},\"f:operatingSystem\":{},\"f:osImage\":{},\"f:systemUUID\":{}}}}},{\"manager\":\"kubectl-label\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-07-21T23:40:53Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:metadata\":{\"f:labels\":{\"f:kubernetes.io/role\":{},\"f:node-role.kubernetes.io/agent\":{}}}}},{\"manager\":\"node-problem-detector\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-08-10T18:10:02Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:status\":{\"f:conditions\":{\"k:{\\\"type\\\":\\\"ContainerRuntimeProblem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FilesystemCorruptionProblem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FreezeScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentContainerdRestart\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentDockerRestart\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentKubeletRestart\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentUnregisterNetDevice\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"KernelDeadlock\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"KubeletProblem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"PreemptScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"ReadonlyFilesystem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"RebootScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"RedeployScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"TerminateScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}}}}}}]},\"spec\":{\"providerID\":\"azure:///subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/mc_davidaks16_davidaks16_westus2/providers/Microsoft.Compute/virtualMachineScaleSets/aks-nodepool1-24816391-vmss/virtualMachines/0\"},\"status\":{\"capacity\":{\"attachable-volumes-azure-disk\":\"8\",\"cpu\":\"2\",\"ephemeral-storage\":\"129900528Ki\",\"hugepages-1Gi\":\"0\",\"hugepages-2Mi\":\"0\",\"memory\":\"7120616Ki\",\"pods\":\"30\"},\"allocatable\":{\"attachable-volumes-azure-disk\":\"8\",\"cpu\":\"1900m\",\"ephemeral-storage\":\"119716326407\",\"hugepages-1Gi\":\"0\",\"hugepages-2Mi\":\"0\",\"memory\":\"4675304Ki\",\"pods\":\"30\"},\"conditions\":[{\"type\":\"FrequentContainerdRestart\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentContainerdRestart\",\"message\":\"containerd is functioning properly\"},{\"type\":\"FreezeScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFreezeScheduled\",\"message\":\"VM has no scheduled Freeze event\"},{\"type\":\"FrequentDockerRestart\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentDockerRestart\",\"message\":\"docker is functioning properly\"},{\"type\":\"FilesystemCorruptionProblem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"FilesystemIsOK\",\"message\":\"Filesystem is healthy\"},{\"type\":\"KernelDeadlock\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"KernelHasNoDeadlock\",\"message\":\"kernel has no deadlock\"},{\"type\":\"TerminateScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoTerminateScheduled\",\"message\":\"VM has no scheduled Terminate event\"},{\"type\":\"ReadonlyFilesystem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"FilesystemIsNotReadOnly\",\"message\":\"Filesystem is not read-only\"},{\"type\":\"FrequentUnregisterNetDevice\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentUnregisterNetDevice\",\"message\":\"node is functioning properly\"},{\"type\":\"KubeletProblem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"KubeletIsUp\",\"message\":\"kubelet service is up\"},{\"type\":\"PreemptScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:11:11Z\",\"reason\":\"NoPreemptScheduled\",\"message\":\"VM has no scheduled Preempt event\"},{\"type\":\"RedeployScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoRedeployScheduled\",\"message\":\"VM has no scheduled Redeploy event\"},{\"type\":\"ContainerRuntimeProblem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"ContainerRuntimeIsUp\",\"message\":\"container runtime service is up\"},{\"type\":\"FrequentKubeletRestart\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentKubeletRestart\",\"message\":\"kubelet is functioning properly\"},{\"type\":\"RebootScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoRebootScheduled\",\"message\":\"VM has no scheduled Reboot event\"},{\"type\":\"MemoryPressure\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:14Z\",\"reason\":\"KubeletHasSufficientMemory\",\"message\":\"kubelet has sufficient memory available\"},{\"type\":\"DiskPressure\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:14Z\",\"reason\":\"KubeletHasNoDiskPressure\",\"message\":\"kubelet has no disk pressure\"},{\"type\":\"PIDPressure\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:14Z\",\"reason\":\"KubeletHasSufficientPID\",\"message\":\"kubelet has sufficient PID available\"},{\"type\":\"Ready\",\"status\":\"True\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:24Z\",\"reason\":\"KubeletReady\",\"message\":\"kubelet is posting ready status. AppArmor enabled\"}],\"addresses\":[{\"type\":\"Hostname\",\"address\":\"aks-nodepool1-24816391-vmss000000\"},{\"type\":\"InternalIP\",\"address\":\"10.240.0.4\"}],\"daemonEndpoints\":{\"kubeletEndpoint\":{\"Port\":10250}},\"nodeInfo\":{\"machineID\":\"17a654260e2c4a9bb3a3eb4b4188e4b4\",\"systemUUID\":\"7ff599e4-909e-4950-a044-ff8613af3af9\",\"bootID\":\"02bb865b-a469-43cd-8b0b-5ceb4ecd80b0\",\"kernelVersion\":\"5.4.0-1051-azure\",\"osImage\":\"Ubuntu 18.04.5 LTS\",\"containerRuntimeVersion\":\"containerd://1.4.4+azure\",\"kubeletVersion\":\"v1.19.11\",\"kubeProxyVersion\":\"v1.19.11\",\"operatingSystem\":\"linux\",\"architecture\":\"amd64\"},\"images\":[{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021-1\"],\"sizeBytes\":331689060},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021\"],\"sizeBytes\":330099815},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021-hotfix\"],\"sizeBytes\":271471426},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021\"],\"sizeBytes\":269703297},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod03262021\"],\"sizeBytes\":264732875},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.19.0\"],\"sizeBytes\":166352383},{\"names\":[\"mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210623.2\"],\"sizeBytes\":147750148},{\"names\":[\"mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210524.1\"],\"sizeBytes\":146446618},{\"names\":[\"mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210427.1\"],\"sizeBytes\":136242776},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.8.9.5\"],\"sizeBytes\":101794833},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.47.0\"],\"sizeBytes\":101445696},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/autoscaler/cluster-proportional-autoscaler:1.3.0_v0.0.5\"],\"sizeBytes\":101194562},{\"names\":[\"mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210623.2\"],\"sizeBytes\":96125176},{\"names\":[\"mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210524.1\"],\"sizeBytes\":95879501},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/exechealthz:1.2_v0.0.5\"],\"sizeBytes\":94348102},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.8.9.2\"],\"sizeBytes\":93537927},{\"names\":[\"mcr.microsoft.com/aks/acc/sgx-attestation:2.0\"],\"sizeBytes\":91841669},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.4.0\"],\"sizeBytes\":91324193},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.2.0\"],\"sizeBytes\":89103171},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.0.1-rc3\"],\"sizeBytes\":86839805},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.2.0\"],\"sizeBytes\":86488586},{\"names\":[\"mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210427.1\"],\"sizeBytes\":86120048},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.3.0\"],\"sizeBytes\":81252495},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.4.0\"],\"sizeBytes\":79586703},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.4.0\"],\"sizeBytes\":78795016},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.2.0\"],\"sizeBytes\":76527179},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.1.8\"],\"sizeBytes\":75025803},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.2.2_hotfix\"],\"sizeBytes\":73533889},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.3.1\"],\"sizeBytes\":72242894},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.2.8\"],\"sizeBytes\":70622822},{\"names\":[\"mcr.microsoft.com/oss/nvidia/k8s-device-plugin:v0.9.0\"],\"sizeBytes\":67291599},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.1\"],\"sizeBytes\":66415836},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc7\"],\"sizeBytes\":65965658},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.2.1\"],\"sizeBytes\":64123775},{\"names\":[\"mcr.microsoft.com/oss/calico/cni:v3.8.9.3\"],\"sizeBytes\":63581323},{\"names\":[\"mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8\"],\"sizeBytes\":63154716},{\"names\":[\"mcr.microsoft.com/oss/calico/cni:v3.8.9.2\"],\"sizeBytes\":61626312},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.18.1\"],\"sizeBytes\":60500885},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.17.2\"],\"sizeBytes\":58419768},{\"names\":[\"mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8_hotfix\",\"mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8post2\"],\"sizeBytes\":56368756},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:282543237a1aa3f407656290f454b7068a92e1abe2156082c750d5abfbcad90c\",\"mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.2\"],\"sizeBytes\":56310724},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.19.0\"],\"sizeBytes\":55228749},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.1\"],\"sizeBytes\":54692048},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc3\"],\"sizeBytes\":50803639},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.19\"],\"sizeBytes\":49759361},{\"names\":[\"mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.5\"],\"sizeBytes\":49704644},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.21\"],\"sizeBytes\":49372390},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:a64d3538b72905b07356881314755b02db3675ff47ee2bcc49dd7be856e285d5\",\"mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526\"],\"sizeBytes\":49322942},{\"names\":[\"mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.4\"],\"sizeBytes\":48108311},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kubernetes-dashboard:v1.10.1\"],\"sizeBytes\":44907744}],\"config\":{}}}]}\n" - end - end - class << self - def getKubeResourceInfo(resource, api_group: nil) - if resource == "nodes?fieldSelector=metadata.name%3DWIN-T14B9CT7KMS" - return GetNodesResponse.new() - end - # this means that a saved input is missing - byebug - end - end - end env = {"CONTROLLER_TYPE" => "ReplicaSet", "OS_TYPE" => "linux", diff --git a/source/plugins/ruby/in_kube_nodes.rb b/source/plugins/ruby/in_kube_nodes.rb index bc62756a1..ff3b4d919 100644 --- a/source/plugins/ruby/in_kube_nodes.rb +++ b/source/plugins/ruby/in_kube_nodes.rb @@ -7,26 +7,9 @@ module Fluent::Plugin class Kube_nodeInventory_Input < Input Fluent::Plugin.register_input("kube_nodes", self) - @@configMapMountPath = "/etc/config/settings/log-data-collection-settings" - @@promConfigMountPath = "/etc/config/settings/prometheus-data-collection-settings" - @@osmConfigMountPath = "/etc/config/osm-settings/osm-metric-collection-configuration" - @@AzStackCloudFileName = "/etc/kubernetes/host/azurestackcloud.json" - - - @@rsPromInterval = ENV["TELEMETRY_RS_PROM_INTERVAL"] - @@rsPromFieldPassCount = ENV["TELEMETRY_RS_PROM_FIELDPASS_LENGTH"] - @@rsPromFieldDropCount = ENV["TELEMETRY_RS_PROM_FIELDDROP_LENGTH"] - @@rsPromK8sServiceCount = ENV["TELEMETRY_RS_PROM_K8S_SERVICES_LENGTH"] - @@rsPromUrlCount = ENV["TELEMETRY_RS_PROM_URLS_LENGTH"] - @@rsPromMonitorPods = ENV["TELEMETRY_RS_PROM_MONITOR_PODS"] - @@rsPromMonitorPodsNamespaceLength = ENV["TELEMETRY_RS_PROM_MONITOR_PODS_NS_LENGTH"] - @@rsPromMonitorPodsLabelSelectorLength = ENV["TELEMETRY_RS_PROM_LABEL_SELECTOR_LENGTH"] - @@rsPromMonitorPodsFieldSelectorLength = ENV["TELEMETRY_RS_PROM_FIELD_SELECTOR_LENGTH"] - @@collectAllKubeEvents = ENV["AZMON_CLUSTER_COLLECT_ALL_KUBE_EVENTS"] - @@osmNamespaceCount = ENV["TELEMETRY_OSM_CONFIGURATION_NAMESPACES_COUNT"] - - def initialize - super + def initialize (kubernetesApiClient=nil, applicationInsightsUtility=nil, extensionUtils=nil, env=nil) + super() + require "yaml" require "yajl/json_gem" require "yajl" @@ -34,10 +17,35 @@ def initialize require_relative "KubernetesApiClient" require_relative "ApplicationInsightsUtility" - require_relative "oms_common" - require_relative "omslog" + # TODO: oms_common and omslog appear to be unused. + # require_relative "oms_common" + # require_relative "omslog" require_relative "extension_utils" + @kubernetesApiClient = kubernetesApiClient == nil ? KubernetesApiClient : kubernetesApiClient + @applicationInsightsUtility = applicationInsightsUtility == nil ? ApplicationInsightsUtility : applicationInsightsUtility + @extensionUtils = extensionUtils == nil ? ExtensionUtils : extensionUtils + @env = env == nil ? ENV : env + + # these defines were previously at class scope Moving them into the constructor so that they can be set by unit tests + @@configMapMountPath = "/etc/config/settings/log-data-collection-settings" + @@promConfigMountPath = "/etc/config/settings/prometheus-data-collection-settings" + @@osmConfigMountPath = "/etc/config/osm-settings/osm-metric-collection-configuration" + @@AzStackCloudFileName = "/etc/kubernetes/host/azurestackcloud.json" + + + @@rsPromInterval = @env["TELEMETRY_RS_PROM_INTERVAL"] + @@rsPromFieldPassCount = @env["TELEMETRY_RS_PROM_FIELDPASS_LENGTH"] + @@rsPromFieldDropCount = @env["TELEMETRY_RS_PROM_FIELDDROP_LENGTH"] + @@rsPromK8sServiceCount = @env["TELEMETRY_RS_PROM_K8S_SERVICES_LENGTH"] + @@rsPromUrlCount = @env["TELEMETRY_RS_PROM_URLS_LENGTH"] + @@rsPromMonitorPods = @env["TELEMETRY_RS_PROM_MONITOR_PODS"] + @@rsPromMonitorPodsNamespaceLength = @env["TELEMETRY_RS_PROM_MONITOR_PODS_NS_LENGTH"] + @@rsPromMonitorPodsLabelSelectorLength = @env["TELEMETRY_RS_PROM_LABEL_SELECTOR_LENGTH"] + @@rsPromMonitorPodsFieldSelectorLength = @env["TELEMETRY_RS_PROM_FIELD_SELECTOR_LENGTH"] + @@collectAllKubeEvents = @env["AZMON_CLUSTER_COLLECT_ALL_KUBE_EVENTS"] + @@osmNamespaceCount = @env["TELEMETRY_OSM_CONFIGURATION_NAMESPACES_COUNT"] + @ContainerNodeInventoryTag = "oneagent.containerInsights.CONTAINER_NODE_INVENTORY_BLOB" @insightsMetricsTag = "oneagent.containerInsights.INSIGHTS_METRICS_BLOB" @MDMKubeNodeInventoryTag = "mdm.kubenodeinventory" @@ -52,6 +60,9 @@ def initialize require_relative "constants" @NodeCache = NodeStatsCache.new() + + # this is so that telemetry can be unit tested in a reasonable amount of time + @TELEMETRY_FLUSH_INTERVAL_IN_MINUTES = Constants::TELEMETRY_FLUSH_INTERVAL_IN_MINUTES end config_param :run_interval, :time, :default => 60 @@ -64,8 +75,8 @@ def configure(conf) def start if @run_interval super - if !ENV["NODES_CHUNK_SIZE"].nil? && !ENV["NODES_CHUNK_SIZE"].empty? && ENV["NODES_CHUNK_SIZE"].to_i > 0 - @NODES_CHUNK_SIZE = ENV["NODES_CHUNK_SIZE"].to_i + if !@env["NODES_CHUNK_SIZE"].nil? && !@env["NODES_CHUNK_SIZE"].empty? && @env["NODES_CHUNK_SIZE"].to_i > 0 + @NODES_CHUNK_SIZE = @env["NODES_CHUNK_SIZE"].to_i else # this shouldnt happen just setting default here as safe guard $log.warn("in_kube_nodes::start: setting to default value since got NODES_CHUNK_SIZE nil or empty") @@ -73,8 +84,8 @@ def start end $log.info("in_kube_nodes::start : NODES_CHUNK_SIZE @ #{@NODES_CHUNK_SIZE}") - if !ENV["NODES_EMIT_STREAM_BATCH_SIZE"].nil? && !ENV["NODES_EMIT_STREAM_BATCH_SIZE"].empty? && ENV["NODES_EMIT_STREAM_BATCH_SIZE"].to_i > 0 - @NODES_EMIT_STREAM_BATCH_SIZE = ENV["NODES_EMIT_STREAM_BATCH_SIZE"].to_i + if !@env["NODES_EMIT_STREAM_BATCH_SIZE"].nil? && !@env["NODES_EMIT_STREAM_BATCH_SIZE"].empty? && @env["NODES_EMIT_STREAM_BATCH_SIZE"].to_i > 0 + @NODES_EMIT_STREAM_BATCH_SIZE = @env["NODES_EMIT_STREAM_BATCH_SIZE"].to_i else # this shouldnt happen just setting default here as safe guard $log.warn("in_kube_nodes::start: setting to default value since got NODES_EMIT_STREAM_BATCH_SIZE nil or empty") @@ -112,19 +123,19 @@ def enumerate @nodeInventoryE2EProcessingLatencyMs = 0 nodeInventoryStartTime = (Time.now.to_f * 1000).to_i - if ExtensionUtils.isAADMSIAuthMode() + if @extensionUtils.isAADMSIAuthMode() $log.info("in_kube_nodes::enumerate: AAD AUTH MSI MODE") if @kubeperfTag.nil? || !@kubeperfTag.start_with?(Constants::EXTENSION_OUTPUT_STREAM_ID_TAG_PREFIX) - @kubeperfTag = ExtensionUtils.getOutputStreamId(Constants::PERF_DATA_TYPE) + @kubeperfTag = @extensionUtils.getOutputStreamId(Constants::PERF_DATA_TYPE) end if @insightsMetricsTag.nil? || !@insightsMetricsTag.start_with?(Constants::EXTENSION_OUTPUT_STREAM_ID_TAG_PREFIX) - @insightsMetricsTag = ExtensionUtils.getOutputStreamId(Constants::INSIGHTS_METRICS_DATA_TYPE) + @insightsMetricsTag = @extensionUtils.getOutputStreamId(Constants::INSIGHTS_METRICS_DATA_TYPE) end if @ContainerNodeInventoryTag.nil? || !@ContainerNodeInventoryTag.start_with?(Constants::EXTENSION_OUTPUT_STREAM_ID_TAG_PREFIX) - @ContainerNodeInventoryTag = ExtensionUtils.getOutputStreamId(Constants::CONTAINER_NODE_INVENTORY_DATA_TYPE) + @ContainerNodeInventoryTag = @extensionUtils.getOutputStreamId(Constants::CONTAINER_NODE_INVENTORY_DATA_TYPE) end if @tag.nil? || !@tag.start_with?(Constants::EXTENSION_OUTPUT_STREAM_ID_TAG_PREFIX) - @tag = ExtensionUtils.getOutputStreamId(Constants::KUBE_NODE_INVENTORY_DATA_TYPE) + @tag = @extensionUtils.getOutputStreamId(Constants::KUBE_NODE_INVENTORY_DATA_TYPE) end $log.info("in_kube_nodes::enumerate: using perf tag -#{@kubeperfTag} @ #{Time.now.utc.iso8601}") $log.info("in_kube_nodes::enumerate: using insightsmetrics tag -#{@insightsMetricsTag} @ #{Time.now.utc.iso8601}") @@ -137,7 +148,7 @@ def enumerate continuationToken = nil $log.info("in_kube_nodes::enumerate : Getting nodes from Kube API @ #{Time.now.utc.iso8601}") resourceUri = KubernetesApiClient.getNodesResourceUri("nodes?limit=#{@NODES_CHUNK_SIZE}") - continuationToken, nodeInventory = KubernetesApiClient.getResourcesAndContinuationToken(resourceUri) + continuationToken, nodeInventory = @kubernetesApiClient.getResourcesAndContinuationToken(resourceUri) $log.info("in_kube_nodes::enumerate : Done getting nodes from Kube API @ #{Time.now.utc.iso8601}") nodesAPIChunkEndTime = (Time.now.to_f * 1000).to_i @nodesAPIE2ELatencyMs = (nodesAPIChunkEndTime - nodesAPIChunkStartTime) @@ -151,7 +162,7 @@ def enumerate #If we receive a continuation token, make calls, process and flush data until we have processed all data while (!continuationToken.nil? && !continuationToken.empty?) nodesAPIChunkStartTime = (Time.now.to_f * 1000).to_i - continuationToken, nodeInventory = KubernetesApiClient.getResourcesAndContinuationToken(resourceUri + "&continue=#{continuationToken}") + continuationToken, nodeInventory = @kubernetesApiClient.getResourcesAndContinuationToken(resourceUri + "&continue=#{continuationToken}") nodesAPIChunkEndTime = (Time.now.to_f * 1000).to_i @nodesAPIE2ELatencyMs = @nodesAPIE2ELatencyMs + (nodesAPIChunkEndTime - nodesAPIChunkStartTime) if (!nodeInventory.nil? && !nodeInventory.empty? && nodeInventory.key?("items") && !nodeInventory["items"].nil? && !nodeInventory["items"].empty?) @@ -165,9 +176,9 @@ def enumerate @nodeInventoryE2EProcessingLatencyMs = ((Time.now.to_f * 1000).to_i - nodeInventoryStartTime) timeDifference = (DateTime.now.to_time.to_i - @@nodeInventoryLatencyTelemetryTimeTracker).abs timeDifferenceInMinutes = timeDifference / 60 - if (timeDifferenceInMinutes >= Constants::TELEMETRY_FLUSH_INTERVAL_IN_MINUTES) - ApplicationInsightsUtility.sendMetricTelemetry("NodeInventoryE2EProcessingLatencyMs", @nodeInventoryE2EProcessingLatencyMs, {}) - ApplicationInsightsUtility.sendMetricTelemetry("NodesAPIE2ELatencyMs", @nodesAPIE2ELatencyMs, {}) + if (timeDifferenceInMinutes >= @TELEMETRY_FLUSH_INTERVAL_IN_MINUTES) + @applicationInsightsUtility.sendMetricTelemetry("NodeInventoryE2EProcessingLatencyMs", @nodeInventoryE2EProcessingLatencyMs, {}) + @applicationInsightsUtility.sendMetricTelemetry("NodesAPIE2ELatencyMs", @nodesAPIE2ELatencyMs, {}) @@nodeInventoryLatencyTelemetryTimeTracker = DateTime.now.to_time.to_i end # Setting this to nil so that we dont hold memory until GC kicks in @@ -175,7 +186,7 @@ def enumerate rescue => errorStr $log.warn "in_kube_nodes::enumerate:Failed in enumerate: #{errorStr}" $log.debug_backtrace(errorStr.backtrace) - ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) + @applicationInsightsUtility.sendExceptionTelemetry(errorStr) end end # end enumerate @@ -188,7 +199,7 @@ def parse_and_emit_records(nodeInventory, batchTime = Time.utc.iso8601) containerNodeInventoryEventStream = Fluent::MultiEventStream.new insightsMetricsEventStream = Fluent::MultiEventStream.new kubePerfEventStream = Fluent::MultiEventStream.new - @@istestvar = ENV["ISTEST"] + @@istestvar = @env["ISTEST"] #get node inventory nodeInventory["items"].each do |item| # node inventory @@ -299,12 +310,12 @@ def parse_and_emit_records(nodeInventory, batchTime = Time.utc.iso8601) # Adding telemetry to send node telemetry every 10 minutes timeDifference = (DateTime.now.to_time.to_i - @@nodeTelemetryTimeTracker).abs timeDifferenceInMinutes = timeDifference / 60 - if (timeDifferenceInMinutes >= Constants::TELEMETRY_FLUSH_INTERVAL_IN_MINUTES) + if (timeDifferenceInMinutes >= @TELEMETRY_FLUSH_INTERVAL_IN_MINUTES) properties = getNodeTelemetryProps(item) properties["KubernetesProviderID"] = nodeInventoryRecord["KubernetesProviderID"] capacityInfo = item["status"]["capacity"] - ApplicationInsightsUtility.sendMetricTelemetry("NodeMemory", capacityInfo["memory"], properties) + @applicationInsightsUtility.sendMetricTelemetry("NodeMemory", capacityInfo["memory"], properties) begin if (!capacityInfo["nvidia.com/gpu"].nil?) && (!capacityInfo["nvidia.com/gpu"].empty?) properties["nvigpus"] = capacityInfo["nvidia.com/gpu"] @@ -316,7 +327,7 @@ def parse_and_emit_records(nodeInventory, batchTime = Time.utc.iso8601) rescue => errorStr $log.warn "Failed in getting GPU telemetry in_kube_nodes : #{errorStr}" $log.debug_backtrace(errorStr.backtrace) - ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) + @applicationInsightsUtility.sendExceptionTelemetry(errorStr) end # Telemetry for data collection config for replicaset @@ -340,7 +351,7 @@ def parse_and_emit_records(nodeInventory, batchTime = Time.utc.iso8601) if (File.file?(@@osmConfigMountPath)) properties["osmNamespaceCount"] = @@osmNamespaceCount end - ApplicationInsightsUtility.sendMetricTelemetry("NodeCoreCapacity", capacityInfo["cpu"], properties) + @applicationInsightsUtility.sendMetricTelemetry("NodeCoreCapacity", capacityInfo["cpu"], properties) telemetrySent = true end end @@ -385,7 +396,7 @@ def parse_and_emit_records(nodeInventory, batchTime = Time.utc.iso8601) rescue => errorStr $log.warn "Failed to retrieve node inventory: #{errorStr}" $log.debug_backtrace(errorStr.backtrace) - ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) + @applicationInsightsUtility.sendExceptionTelemetry(errorStr) end $log.info "in_kube_nodes::parse_and_emit_records:End #{Time.now.utc.iso8601}" end @@ -414,7 +425,7 @@ def run_periodic $log.info("in_kube_nodes::run_periodic.enumerate.end #{Time.now.utc.iso8601}") rescue => errorStr $log.warn "in_kube_nodes::run_periodic: enumerate Failed to retrieve node inventory: #{errorStr}" - ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) + @applicationInsightsUtility.sendExceptionTelemetry(errorStr) end end @mutex.lock @@ -428,8 +439,8 @@ def getNodeInventoryRecord(item, batchTime = Time.utc.iso8601) begin record["CollectionTime"] = batchTime #This is the time that is mapped to become TimeGenerated record["Computer"] = item["metadata"]["name"] - record["ClusterName"] = KubernetesApiClient.getClusterName - record["ClusterId"] = KubernetesApiClient.getClusterId + record["ClusterName"] = @kubernetesApiClient.getClusterName + record["ClusterId"] = @kubernetesApiClient.getClusterId record["CreationTimeStamp"] = item["metadata"]["creationTimestamp"] record["Labels"] = [item["metadata"]["labels"]] record["Status"] = "" @@ -528,7 +539,14 @@ def getNodeTelemetryProps(item) end return properties end + + # this is used in + def set_telemetry_flush_interval(interval) + @TELEMETRY_FLUSH_INTERVAL_IN_MINUTES = interval + end end # Kube_Node_Input + + class NodeStatsCache # inner class for caching implementation (CPU and memory caching is handled the exact same way, so logic to do so is moved to a private inner class) # (to reduce code duplication) diff --git a/source/plugins/ruby/in_kube_nodes_test.rb b/source/plugins/ruby/in_kube_nodes_test.rb new file mode 100644 index 000000000..6d1ea5610 --- /dev/null +++ b/source/plugins/ruby/in_kube_nodes_test.rb @@ -0,0 +1,147 @@ +# TODO: can we get rid of this global flag +$in_unit_test = true + +require 'minitest/autorun' + +require 'fluent/test' +require 'fluent/test/driver/input' +require 'fluent/test/helpers' + +require_relative 'in_kube_nodes.rb' +require 'byebug' + +class MyInputTest < Minitest::Test + include Fluent::Test::Helpers + + def setup + Fluent::Test.setup + end + + def create_driver(conf = {}, kubernetesApiClient=nil, applicationInsightsUtility=nil, extensionUtils=nil, env=nil) + Fluent::Test::Driver::Input.new(Fluent::Plugin::Kube_nodeInventory_Input.new(kubernetesApiClient=kubernetesApiClient, + applicationInsightsUtility=applicationInsightsUtility, + extensionUtils=extensionUtils, + env=env)).configure(conf) + end + + def overwrite_collection_time(data) + if data.key?("CollectionTime") + data["CollectionTime"] = "~CollectionTime~" + end + if data.key?("Timestamp") + data["Timestamp"] = "~Timestamp~" + end + return data + end + + def test_basic_single_node + kubeApiClient = Minitest::Mock.new + appInsightsUtil = Minitest::Mock.new + extensionUtils = Minitest::Mock.new + env = {} + env["NODES_CHUNK_SIZE"] = "200" + + kubeApiClient.expect(:==, false, [nil]) + appInsightsUtil.expect(:==, false, [nil]) + extensionUtils.expect(:==, false, [nil]) + + # isAADMSIAuthMode() is called multiple times and we don't really care how many time it is called. This is the same as mocking + # but it doesn't track how many times isAADMSIAuthMode is called + def extensionUtils.isAADMSIAuthMode + false + end + + nodes_api_response = eval(File.open("../../../test/unit-tests/canned-api-responses/kube-nodes.txt").read) + kubeApiClient.expect(:getResourcesAndContinuationToken, [nil, nodes_api_response], ["nodes?limit=200"]) + kubeApiClient.expect(:getClusterName, "/cluster-name") + kubeApiClient.expect(:getClusterId, "/cluster-id") + + config = "run_interval 999999999" # only run once + + d = create_driver(config, kubernetesApiClient=kubeApiClient, applicationInsightsUtility=appInsightsUtil, extensionUtils=extensionUtils, env=env) + d.instance.start + d.instance.enumerate + d.run(timeout: 99999) # Input plugins decide when to run, so we have to give it enough time to run + + + expected_responses = { ["oneagent.containerInsights.KUBE_NODE_INVENTORY_BLOB", overwrite_collection_time({"CollectionTime"=>"2021-08-17T20:24:18Z", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"aks-nodepool1-24816391-vmss000000", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"})] => true, + ["mdm.kubenodeinventory", overwrite_collection_time({"CollectionTime"=>"2021-08-17T20:24:18Z", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"aks-nodepool1-24816391-vmss000000", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"})] => true, + ["oneagent.containerInsights.CONTAINER_NODE_INVENTORY_BLOB", overwrite_collection_time({"CollectionTime"=>"2021-08-17T20:24:18Z", "Computer"=>"aks-nodepool1-24816391-vmss000000", "OperatingSystem"=>"Ubuntu 18.04.5 LTS", "DockerVersion"=>"containerd://1.4.4+azure"})] => true, + ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"cpuAllocatableNanoCores\",\"Value\":1900000000.0}]"})] => true, + ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"memoryAllocatableBytes\",\"Value\":4787511296.0}]"})] => true, + ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"cpuCapacityNanoCores\",\"Value\":2000000000.0}]"})] => true, + ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"memoryCapacityBytes\",\"Value\":7291510784.0}]"})] => true} + + d.events.each do |tag, time, record| + cleaned_record = overwrite_collection_time record + if expected_responses.key?([tag, cleaned_record]) + assert_equal(true, true) + else + assert_equal(true, false) + end + end + + kubeApiClient.verify + appInsightsUtil.verify + extensionUtils.verify + end + + + def test_malformed_node_spec + kubeApiClient = Minitest::Mock.new + appInsightsUtil = Minitest::Mock.new + extensionUtils = Minitest::Mock.new + env = {} + env["NODES_CHUNK_SIZE"] = "200" + + kubeApiClient.expect(:==, false, [nil]) + appInsightsUtil.expect(:==, false, [nil]) + extensionUtils.expect(:==, false, [nil]) + + # isAADMSIAuthMode() is called multiple times and we don't really care how many time it is called. This is the same as mocking + # but it doesn't track how many times isAADMSIAuthMode is called + def extensionUtils.isAADMSIAuthMode + false + end + + nodes_api_response = eval(File.open("../../../test/unit-tests/canned-api-responses/kube-nodes-malformed.txt").read) + kubeApiClient.expect(:getResourcesAndContinuationToken, [nil, nodes_api_response], ["nodes?limit=200"]) + kubeApiClient.expect(:getClusterName, "/cluster-name") + kubeApiClient.expect(:getClusterId, "/cluster-id") + + config = "run_interval 999999999" # only run once + + d = create_driver(config, kubernetesApiClient=kubeApiClient, applicationInsightsUtility=appInsightsUtil, extensionUtils=extensionUtils, env=env) + d.instance.start + d.instance.set_telemetry_flush_interval(0) + + byebug + + d.instance.enumerate + d.run(timeout: 99999) # Input plugins decide when to run, so we have to give it enough time to run + + + expected_responses = { ["oneagent.containerInsights.KUBE_NODE_INVENTORY_BLOB", overwrite_collection_time({"CollectionTime"=>"2021-08-17T20:24:18Z", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"aks-nodepool1-24816391-vmss000000", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"})] => true, + ["mdm.kubenodeinventory", overwrite_collection_time({"CollectionTime"=>"2021-08-17T20:24:18Z", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"aks-nodepool1-24816391-vmss000000", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"})] => true, + ["oneagent.containerInsights.CONTAINER_NODE_INVENTORY_BLOB", overwrite_collection_time({"CollectionTime"=>"2021-08-17T20:24:18Z", "Computer"=>"aks-nodepool1-24816391-vmss000000", "OperatingSystem"=>"Ubuntu 18.04.5 LTS", "DockerVersion"=>"containerd://1.4.4+azure"})] => true, + ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"cpuAllocatableNanoCores\",\"Value\":1900000000.0}]"})] => true, + ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"memoryAllocatableBytes\",\"Value\":4787511296.0}]"})] => true, + ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"cpuCapacityNanoCores\",\"Value\":2000000000.0}]"})] => true, + ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"memoryCapacityBytes\",\"Value\":7291510784.0}]"})] => true} + + d.events.each do |tag, time, record| + cleaned_record = overwrite_collection_time record + if expected_responses.key?([tag, cleaned_record]) + assert_equal(true, true) + else + assert_equal(true, false) + end + end + + kubeApiClient.verify + appInsightsUtil.verify + extensionUtils.verify + end + + +end diff --git a/source/plugins/ruby/test_driver.rb b/source/plugins/ruby/test_driver.rb new file mode 100644 index 000000000..aca4129a5 --- /dev/null +++ b/source/plugins/ruby/test_driver.rb @@ -0,0 +1,6 @@ +# TODO: can we get rid of this global flag +$in_unit_test = true + +Dir.glob("*_test.rb") do |filename| + require_relative filename +end diff --git a/test/unit-tests/canned-api-responses/kube-nodes-malformed.txt b/test/unit-tests/canned-api-responses/kube-nodes-malformed.txt new file mode 100644 index 000000000..9aa10b6f1 --- /dev/null +++ b/test/unit-tests/canned-api-responses/kube-nodes-malformed.txt @@ -0,0 +1,832 @@ +{ + "kind"=>"NodeList", + "apiVersion"=>"v1", + "metadata"=>{ + "selfLink"=>"/api/v1/nodes", + "resourceVersion"=>"5974879" + }, + "items"=>[ + { + "metadata"=>{ + "name"=>"aks-nodepool1-24816391-vmss000000", + "selfLink"=>"/api/v1/nodes/aks-nodepool1-24816391-vmss000000", + "uid"=>"fe073f0a-e6bf-4d68-b4e5-ffaa42b91528", + "resourceVersion"=>"5974522", + "creationTimestamp"=>"2021-07-21T23:40:14Z", + "labels"=>{ + "agentpool"=>"nodepool1", + "beta.kubernetes.io/arch"=>"amd64", + "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", + "beta.kubernetes.io/os"=>"linux", + "failure-domain.beta.kubernetes.io/region"=>"westus2", + "failure-domain.beta.kubernetes.io/zone"=>"0", + "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", + "kubernetes.azure.com/mode"=>"system", + "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", + "kubernetes.azure.com/os-sku"=>"Ubuntu", + "kubernetes.azure.com/role"=>"agent", + "kubernetes.io/arch"=>"amd64", + "kubernetes.io/hostname"=>"aks-nodepool1-24816391-vmss000000", + "kubernetes.io/os"=>"linux", + "kubernetes.io/role"=>"agent", + "node-role.kubernetes.io/agent"=>"", + "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", + "storageprofile"=>"managed", + "storagetier"=>"Premium_LRS", + "topology.kubernetes.io/region"=>"westus2", + "topology.kubernetes.io/zone"=>"0" + }, + "annotations"=>{ + "node.alpha.kubernetes.io/ttl"=>"0", + "volumes.kubernetes.io/controller-managed-attach-detach"=>"true" + }, + "managedFields"=>[ + { + "manager"=>"kube-controller-manager", + "operation"=>"Update", + "apiVersion"=>"v1", + "time"=>"2021-07-21T23:40:20Z", + "fieldsType"=>"FieldsV1", + "fieldsV1"=>{ + "f:metadata"=>{ + "f:annotations"=>{ + "f:node.alpha.kubernetes.io/ttl"=>{} + } + } + } + }, + { + "manager"=>"kubelet", + "operation"=>"Update", + "apiVersion"=>"v1", + "time"=>"2021-07-21T23:40:24Z", + "fieldsType"=>"FieldsV1", + "fieldsV1"=>{ + "f:metadata"=>{ + "f:annotations"=>{ + "."=>{}, + "f:volumes.kubernetes.io/controller-managed-attach-detach"=>{} + }, + "f:labels"=>{ + "."=>{}, + "f:agentpool"=>{}, + "f:beta.kubernetes.io/arch"=>{}, + "f:beta.kubernetes.io/instance-type"=>{}, + "f:beta.kubernetes.io/os"=>{}, + "f:failure-domain.beta.kubernetes.io/region"=>{}, + "f:failure-domain.beta.kubernetes.io/zone"=>{}, + "f:kubernetes.azure.com/cluster"=>{}, + "f:kubernetes.azure.com/mode"=>{}, + "f:kubernetes.azure.com/node-image-version"=>{}, + "f:kubernetes.azure.com/os-sku"=>{}, + "f:kubernetes.azure.com/role"=>{}, + "f:kubernetes.io/arch"=>{}, + "f:kubernetes.io/hostname"=>{}, + "f:kubernetes.io/os"=>{}, + "f:node.kubernetes.io/instance-type"=>{}, + "f:storageprofile"=>{}, + "f:storagetier"=>{}, + "f:topology.kubernetes.io/region"=>{}, + "f:topology.kubernetes.io/zone"=>{} + } + }, + "f:spec"=>{ + "f:providerID"=>{} + }, + "f:status"=>{ + "f:addresses"=>{ + "."=>{}, + "k:{\"type\":\"Hostname\"}"=>{ + "."=>{}, + "f:address"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"InternalIP\"}"=>{ + "."=>{}, + "f:address"=>{}, + "f:type"=>{} + } + }, + "f:allocatable"=>{ + "."=>{}, + "f:attachable-volumes-azure-disk"=>{}, + "f:cpu"=>{}, + "f:ephemeral-storage"=>{}, + "f:hugepages-1Gi"=>{}, + "f:hugepages-2Mi"=>{}, + "f:memory"=>{}, + "f:pods"=>{} + }, + "f:conditions"=>{ + "."=>{}, + "k:{\"type\":\"DiskPressure\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"MemoryPressure\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"PIDPressure\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"Ready\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + } + }, + "f:config"=>{}, + "f:daemonEndpoints"=>{ + "f:kubeletEndpoint"=>{ + "f:Port"=>{} + } + }, + "f:images"=>{}, + "f:nodeInfo"=>{ + "f:architecture"=>{}, + "f:bootID"=>{}, + "f:containerRuntimeVersion"=>{}, + "f:kernelVersion"=>{}, + "f:kubeProxyVersion"=>{}, + "f:kubeletVersion"=>{}, + "f:machineID"=>{}, + "f:operatingSystem"=>{}, + "f:osImage"=>{}, + "f:systemUUID"=>{} + } + } + } + }, + { + "manager"=>"kubectl-label", + "operation"=>"Update", + "apiVersion"=>"v1", + "time"=>"2021-07-21T23:40:53Z", + "fieldsType"=>"FieldsV1", + "fieldsV1"=>{ + "f:metadata"=>{ + "f:labels"=>{ + "f:kubernetes.io/role"=>{}, + "f:node-role.kubernetes.io/agent"=>{} + } + } + } + }, + { + "manager"=>"node-problem-detector", + "operation"=>"Update", + "apiVersion"=>"v1", + "time"=>"2021-08-10T18:10:02Z", + "fieldsType"=>"FieldsV1", + "fieldsV1"=>{ + "f:status"=>{ + "f:conditions"=>{ + "k:{\"type\":\"ContainerRuntimeProblem\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FilesystemCorruptionProblem\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FreezeScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FrequentContainerdRestart\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FrequentDockerRestart\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FrequentKubeletRestart\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FrequentUnregisterNetDevice\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"KernelDeadlock\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"KubeletProblem\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"PreemptScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"ReadonlyFilesystem\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"RebootScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"RedeployScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"TerminateScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + } + } + } + } + } + ] + }, + "spec"=>{ + "providerID"=>"azure:///subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/mc_davidaks16_davidaks16_westus2/providers/Microsoft.Compute/virtualMachineScaleSets/aks-nodepool1-24816391-vmss/virtualMachines/0" + }, + "status"=>{ + "allocatable"=>{ + "attachable-volumes-azure-disk"=>"8", + "cpu"=>"1900m", + "ephemeral-storage"=>"119716326407", + "hugepages-1Gi"=>"0", + "hugepages-2Mi"=>"0", + "memory"=>"4675304Ki", + "pods"=>"30" + }, + "conditions"=>[ + { + "type"=>"FrequentDockerRestart", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoFrequentDockerRestart", + "message"=>"docker is functioning properly" + }, + { + "type"=>"FilesystemCorruptionProblem", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"FilesystemIsOK", + "message"=>"Filesystem is healthy" + }, + { + "type"=>"KernelDeadlock", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"KernelHasNoDeadlock", + "message"=>"kernel has no deadlock" + }, + { + "type"=>"FrequentContainerdRestart", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoFrequentContainerdRestart", + "message"=>"containerd is functioning properly" + }, + { + "type"=>"FreezeScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-11T23:25:04Z", + "reason"=>"NoFreezeScheduled", + "message"=>"VM has no scheduled Freeze event" + }, + { + "type"=>"FrequentUnregisterNetDevice", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoFrequentUnregisterNetDevice", + "message"=>"node is functioning properly" + }, + { + "type"=>"TerminateScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoTerminateScheduled", + "message"=>"VM has no scheduled Terminate event" + }, + { + "type"=>"ReadonlyFilesystem", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"FilesystemIsNotReadOnly", + "message"=>"Filesystem is not read-only" + }, + { + "type"=>"RedeployScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoRedeployScheduled", + "message"=>"VM has no scheduled Redeploy event" + }, + { + "type"=>"KubeletProblem", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"KubeletIsUp", + "message"=>"kubelet service is up" + }, + { + "type"=>"PreemptScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:11:11Z", + "reason"=>"NoPreemptScheduled", + "message"=>"VM has no scheduled Preempt event" + }, + { + "type"=>"RebootScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoRebootScheduled", + "message"=>"VM has no scheduled Reboot event" + }, + { + "type"=>"ContainerRuntimeProblem", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"ContainerRuntimeIsUp", + "message"=>"container runtime service is up" + }, + { + "type"=>"FrequentKubeletRestart", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoFrequentKubeletRestart", + "message"=>"kubelet is functioning properly" + }, + { + "type"=>"MemoryPressure", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:28:21Z", + "lastTransitionTime"=>"2021-07-21T23:40:14Z", + "reason"=>"KubeletHasSufficientMemory", + "message"=>"kubelet has sufficient memory available" + }, + { + "type"=>"DiskPressure", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:28:21Z", + "lastTransitionTime"=>"2021-07-21T23:40:14Z", + "reason"=>"KubeletHasNoDiskPressure", + "message"=>"kubelet has no disk pressure" + }, + { + "type"=>"PIDPressure", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:28:21Z", + "lastTransitionTime"=>"2021-07-21T23:40:14Z", + "reason"=>"KubeletHasSufficientPID", + "message"=>"kubelet has sufficient PID available" + }, + { + "type"=>"Ready", + "status"=>"True", + "lastHeartbeatTime"=>"2021-08-17T19:28:21Z", + "lastTransitionTime"=>"2021-07-21T23:40:24Z", + "reason"=>"KubeletReady", + "message"=>"kubelet is posting ready status. AppArmor enabled" + } + ], + "addresses"=>[ + { + "type"=>"Hostname", + "address"=>"aks-nodepool1-24816391-vmss000000" + }, + { + "type"=>"InternalIP", + "address"=>"10.240.0.4" + } + ], + "daemonEndpoints"=>{ + "kubeletEndpoint"=>{ + "Port"=>10250 + } + }, + "nodeInfo"=>{ + "machineID"=>"17a654260e2c4a9bb3a3eb4b4188e4b4", + "systemUUID"=>"7ff599e4-909e-4950-a044-ff8613af3af9", + "bootID"=>"02bb865b-a469-43cd-8b0b-5ceb4ecd80b0", + "kernelVersion"=>"5.4.0-1051-azure", + "osImage"=>"Ubuntu 18.04.5 LTS", + "containerRuntimeVersion"=>"containerd://1.4.4+azure", + "kubeletVersion"=>"v1.19.11", + "kubeProxyVersion"=>"v1.19.11", + "operatingSystem"=>"linux", + "architecture"=>"amd64" + }, + "images"=>[ + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021-1" + ], + "sizeBytes"=>331689060 + }, + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021" + ], + "sizeBytes"=>330099815 + }, + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021-hotfix" + ], + "sizeBytes"=>271471426 + }, + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021" + ], + "sizeBytes"=>269703297 + }, + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod03262021" + ], + "sizeBytes"=>264732875 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.19.0" + ], + "sizeBytes"=>166352383 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210623.2" + ], + "sizeBytes"=>147750148 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210524.1" + ], + "sizeBytes"=>146446618 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210427.1" + ], + "sizeBytes"=>136242776 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.8.9.5" + ], + "sizeBytes"=>101794833 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.47.0" + ], + "sizeBytes"=>101445696 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/autoscaler/cluster-proportional-autoscaler:1.3.0_v0.0.5" + ], + "sizeBytes"=>101194562 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210623.2" + ], + "sizeBytes"=>96125176 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210524.1" + ], + "sizeBytes"=>95879501 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/exechealthz:1.2_v0.0.5" + ], + "sizeBytes"=>94348102 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.8.9.2" + ], + "sizeBytes"=>93537927 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/acc/sgx-attestation:2.0" + ], + "sizeBytes"=>91841669 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.4.0" + ], + "sizeBytes"=>91324193 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.2.0" + ], + "sizeBytes"=>89103171 + }, + { + "names"=>[ + "mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.0.1-rc3" + ], + "sizeBytes"=>86839805 + }, + { + "names"=>[ + "mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.2.0" + ], + "sizeBytes"=>86488586 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210427.1" + ], + "sizeBytes"=>86120048 + }, + { + "names"=>[ + "mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.3.0" + ], + "sizeBytes"=>81252495 + }, + { + "names"=>[ + "mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.4.0" + ], + "sizeBytes"=>79586703 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.4.0" + ], + "sizeBytes"=>78795016 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.2.0" + ], + "sizeBytes"=>76527179 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.1.8" + ], + "sizeBytes"=>75025803 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.2.2_hotfix" + ], + "sizeBytes"=>73533889 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.3.1" + ], + "sizeBytes"=>72242894 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.2.8" + ], + "sizeBytes"=>70622822 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/nvidia/k8s-device-plugin:v0.9.0" + ], + "sizeBytes"=>67291599 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.1" + ], + "sizeBytes"=>66415836 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc7" + ], + "sizeBytes"=>65965658 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.2.1" + ], + "sizeBytes"=>64123775 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/cni:v3.8.9.3" + ], + "sizeBytes"=>63581323 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8" + ], + "sizeBytes"=>63154716 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/cni:v3.8.9.2" + ], + "sizeBytes"=>61626312 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.18.1" + ], + "sizeBytes"=>60500885 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.17.2" + ], + "sizeBytes"=>58419768 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8_hotfix", + "mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8post2" + ], + "sizeBytes"=>56368756 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:282543237a1aa3f407656290f454b7068a92e1abe2156082c750d5abfbcad90c", + "mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.2" + ], + "sizeBytes"=>56310724 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.19.0" + ], + "sizeBytes"=>55228749 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.1" + ], + "sizeBytes"=>54692048 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc3" + ], + "sizeBytes"=>50803639 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.19" + ], + "sizeBytes"=>49759361 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.5" + ], + "sizeBytes"=>49704644 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.21" + ], + "sizeBytes"=>49372390 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:a64d3538b72905b07356881314755b02db3675ff47ee2bcc49dd7be856e285d5", + "mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526" + ], + "sizeBytes"=>49322942 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.4" + ], + "sizeBytes"=>48108311 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/kubernetes-dashboard:v1.10.1" + ], + "sizeBytes"=>44907744 + } + ], + "config"=>{} + } + } + ] +} \ No newline at end of file diff --git a/test/unit-tests/canned-api-responses/kube-nodes.txt b/test/unit-tests/canned-api-responses/kube-nodes.txt new file mode 100644 index 000000000..ed411c2e5 --- /dev/null +++ b/test/unit-tests/canned-api-responses/kube-nodes.txt @@ -0,0 +1,851 @@ +{ + "kind"=>"NodeList", + "apiVersion"=>"v1", + "metadata"=>{ + "selfLink"=>"/api/v1/nodes", + "resourceVersion"=>"5974879" + }, + "items"=>[ + { + "metadata"=>{ + "name"=>"aks-nodepool1-24816391-vmss000000", + "selfLink"=>"/api/v1/nodes/aks-nodepool1-24816391-vmss000000", + "uid"=>"fe073f0a-e6bf-4d68-b4e5-ffaa42b91528", + "resourceVersion"=>"5974522", + "creationTimestamp"=>"2021-07-21T23:40:14Z", + "labels"=>{ + "agentpool"=>"nodepool1", + "beta.kubernetes.io/arch"=>"amd64", + "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", + "beta.kubernetes.io/os"=>"linux", + "failure-domain.beta.kubernetes.io/region"=>"westus2", + "failure-domain.beta.kubernetes.io/zone"=>"0", + "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", + "kubernetes.azure.com/mode"=>"system", + "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", + "kubernetes.azure.com/os-sku"=>"Ubuntu", + "kubernetes.azure.com/role"=>"agent", + "kubernetes.io/arch"=>"amd64", + "kubernetes.io/hostname"=>"aks-nodepool1-24816391-vmss000000", + "kubernetes.io/os"=>"linux", + "kubernetes.io/role"=>"agent", + "node-role.kubernetes.io/agent"=>"", + "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", + "storageprofile"=>"managed", + "storagetier"=>"Premium_LRS", + "topology.kubernetes.io/region"=>"westus2", + "topology.kubernetes.io/zone"=>"0" + }, + "annotations"=>{ + "node.alpha.kubernetes.io/ttl"=>"0", + "volumes.kubernetes.io/controller-managed-attach-detach"=>"true" + }, + "managedFields"=>[ + { + "manager"=>"kube-controller-manager", + "operation"=>"Update", + "apiVersion"=>"v1", + "time"=>"2021-07-21T23:40:20Z", + "fieldsType"=>"FieldsV1", + "fieldsV1"=>{ + "f:metadata"=>{ + "f:annotations"=>{ + "f:node.alpha.kubernetes.io/ttl"=>{} + } + } + } + }, + { + "manager"=>"kubelet", + "operation"=>"Update", + "apiVersion"=>"v1", + "time"=>"2021-07-21T23:40:24Z", + "fieldsType"=>"FieldsV1", + "fieldsV1"=>{ + "f:metadata"=>{ + "f:annotations"=>{ + "."=>{}, + "f:volumes.kubernetes.io/controller-managed-attach-detach"=>{} + }, + "f:labels"=>{ + "."=>{}, + "f:agentpool"=>{}, + "f:beta.kubernetes.io/arch"=>{}, + "f:beta.kubernetes.io/instance-type"=>{}, + "f:beta.kubernetes.io/os"=>{}, + "f:failure-domain.beta.kubernetes.io/region"=>{}, + "f:failure-domain.beta.kubernetes.io/zone"=>{}, + "f:kubernetes.azure.com/cluster"=>{}, + "f:kubernetes.azure.com/mode"=>{}, + "f:kubernetes.azure.com/node-image-version"=>{}, + "f:kubernetes.azure.com/os-sku"=>{}, + "f:kubernetes.azure.com/role"=>{}, + "f:kubernetes.io/arch"=>{}, + "f:kubernetes.io/hostname"=>{}, + "f:kubernetes.io/os"=>{}, + "f:node.kubernetes.io/instance-type"=>{}, + "f:storageprofile"=>{}, + "f:storagetier"=>{}, + "f:topology.kubernetes.io/region"=>{}, + "f:topology.kubernetes.io/zone"=>{} + } + }, + "f:spec"=>{ + "f:providerID"=>{} + }, + "f:status"=>{ + "f:addresses"=>{ + "."=>{}, + "k:{\"type\":\"Hostname\"}"=>{ + "."=>{}, + "f:address"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"InternalIP\"}"=>{ + "."=>{}, + "f:address"=>{}, + "f:type"=>{} + } + }, + "f:allocatable"=>{ + "."=>{}, + "f:attachable-volumes-azure-disk"=>{}, + "f:cpu"=>{}, + "f:ephemeral-storage"=>{}, + "f:hugepages-1Gi"=>{}, + "f:hugepages-2Mi"=>{}, + "f:memory"=>{}, + "f:pods"=>{} + }, + "f:capacity"=>{ + "."=>{}, + "f:attachable-volumes-azure-disk"=>{}, + "f:cpu"=>{}, + "f:ephemeral-storage"=>{}, + "f:hugepages-1Gi"=>{}, + "f:hugepages-2Mi"=>{}, + "f:memory"=>{}, + "f:pods"=>{} + }, + "f:conditions"=>{ + "."=>{}, + "k:{\"type\":\"DiskPressure\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"MemoryPressure\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"PIDPressure\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"Ready\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + } + }, + "f:config"=>{}, + "f:daemonEndpoints"=>{ + "f:kubeletEndpoint"=>{ + "f:Port"=>{} + } + }, + "f:images"=>{}, + "f:nodeInfo"=>{ + "f:architecture"=>{}, + "f:bootID"=>{}, + "f:containerRuntimeVersion"=>{}, + "f:kernelVersion"=>{}, + "f:kubeProxyVersion"=>{}, + "f:kubeletVersion"=>{}, + "f:machineID"=>{}, + "f:operatingSystem"=>{}, + "f:osImage"=>{}, + "f:systemUUID"=>{} + } + } + } + }, + { + "manager"=>"kubectl-label", + "operation"=>"Update", + "apiVersion"=>"v1", + "time"=>"2021-07-21T23:40:53Z", + "fieldsType"=>"FieldsV1", + "fieldsV1"=>{ + "f:metadata"=>{ + "f:labels"=>{ + "f:kubernetes.io/role"=>{}, + "f:node-role.kubernetes.io/agent"=>{} + } + } + } + }, + { + "manager"=>"node-problem-detector", + "operation"=>"Update", + "apiVersion"=>"v1", + "time"=>"2021-08-10T18:10:02Z", + "fieldsType"=>"FieldsV1", + "fieldsV1"=>{ + "f:status"=>{ + "f:conditions"=>{ + "k:{\"type\":\"ContainerRuntimeProblem\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FilesystemCorruptionProblem\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FreezeScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FrequentContainerdRestart\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FrequentDockerRestart\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FrequentKubeletRestart\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FrequentUnregisterNetDevice\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"KernelDeadlock\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"KubeletProblem\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"PreemptScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"ReadonlyFilesystem\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"RebootScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"RedeployScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"TerminateScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + } + } + } + } + } + ] + }, + "spec"=>{ + "providerID"=>"azure:///subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/mc_davidaks16_davidaks16_westus2/providers/Microsoft.Compute/virtualMachineScaleSets/aks-nodepool1-24816391-vmss/virtualMachines/0" + }, + "status"=>{ + "capacity"=>{ + "attachable-volumes-azure-disk"=>"8", + "cpu"=>"2", + "ephemeral-storage"=>"129900528Ki", + "hugepages-1Gi"=>"0", + "hugepages-2Mi"=>"0", + "memory"=>"7120616Ki", + "pods"=>"30" + }, + "allocatable"=>{ + "attachable-volumes-azure-disk"=>"8", + "cpu"=>"1900m", + "ephemeral-storage"=>"119716326407", + "hugepages-1Gi"=>"0", + "hugepages-2Mi"=>"0", + "memory"=>"4675304Ki", + "pods"=>"30" + }, + "conditions"=>[ + { + "type"=>"FrequentDockerRestart", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoFrequentDockerRestart", + "message"=>"docker is functioning properly" + }, + { + "type"=>"FilesystemCorruptionProblem", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"FilesystemIsOK", + "message"=>"Filesystem is healthy" + }, + { + "type"=>"KernelDeadlock", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"KernelHasNoDeadlock", + "message"=>"kernel has no deadlock" + }, + { + "type"=>"FrequentContainerdRestart", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoFrequentContainerdRestart", + "message"=>"containerd is functioning properly" + }, + { + "type"=>"FreezeScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-11T23:25:04Z", + "reason"=>"NoFreezeScheduled", + "message"=>"VM has no scheduled Freeze event" + }, + { + "type"=>"FrequentUnregisterNetDevice", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoFrequentUnregisterNetDevice", + "message"=>"node is functioning properly" + }, + { + "type"=>"TerminateScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoTerminateScheduled", + "message"=>"VM has no scheduled Terminate event" + }, + { + "type"=>"ReadonlyFilesystem", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"FilesystemIsNotReadOnly", + "message"=>"Filesystem is not read-only" + }, + { + "type"=>"RedeployScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoRedeployScheduled", + "message"=>"VM has no scheduled Redeploy event" + }, + { + "type"=>"KubeletProblem", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"KubeletIsUp", + "message"=>"kubelet service is up" + }, + { + "type"=>"PreemptScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:11:11Z", + "reason"=>"NoPreemptScheduled", + "message"=>"VM has no scheduled Preempt event" + }, + { + "type"=>"RebootScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoRebootScheduled", + "message"=>"VM has no scheduled Reboot event" + }, + { + "type"=>"ContainerRuntimeProblem", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"ContainerRuntimeIsUp", + "message"=>"container runtime service is up" + }, + { + "type"=>"FrequentKubeletRestart", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoFrequentKubeletRestart", + "message"=>"kubelet is functioning properly" + }, + { + "type"=>"MemoryPressure", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:28:21Z", + "lastTransitionTime"=>"2021-07-21T23:40:14Z", + "reason"=>"KubeletHasSufficientMemory", + "message"=>"kubelet has sufficient memory available" + }, + { + "type"=>"DiskPressure", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:28:21Z", + "lastTransitionTime"=>"2021-07-21T23:40:14Z", + "reason"=>"KubeletHasNoDiskPressure", + "message"=>"kubelet has no disk pressure" + }, + { + "type"=>"PIDPressure", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:28:21Z", + "lastTransitionTime"=>"2021-07-21T23:40:14Z", + "reason"=>"KubeletHasSufficientPID", + "message"=>"kubelet has sufficient PID available" + }, + { + "type"=>"Ready", + "status"=>"True", + "lastHeartbeatTime"=>"2021-08-17T19:28:21Z", + "lastTransitionTime"=>"2021-07-21T23:40:24Z", + "reason"=>"KubeletReady", + "message"=>"kubelet is posting ready status. AppArmor enabled" + } + ], + "addresses"=>[ + { + "type"=>"Hostname", + "address"=>"aks-nodepool1-24816391-vmss000000" + }, + { + "type"=>"InternalIP", + "address"=>"10.240.0.4" + } + ], + "daemonEndpoints"=>{ + "kubeletEndpoint"=>{ + "Port"=>10250 + } + }, + "nodeInfo"=>{ + "machineID"=>"17a654260e2c4a9bb3a3eb4b4188e4b4", + "systemUUID"=>"7ff599e4-909e-4950-a044-ff8613af3af9", + "bootID"=>"02bb865b-a469-43cd-8b0b-5ceb4ecd80b0", + "kernelVersion"=>"5.4.0-1051-azure", + "osImage"=>"Ubuntu 18.04.5 LTS", + "containerRuntimeVersion"=>"containerd://1.4.4+azure", + "kubeletVersion"=>"v1.19.11", + "kubeProxyVersion"=>"v1.19.11", + "operatingSystem"=>"linux", + "architecture"=>"amd64" + }, + "images"=>[ + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021-1" + ], + "sizeBytes"=>331689060 + }, + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021" + ], + "sizeBytes"=>330099815 + }, + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021-hotfix" + ], + "sizeBytes"=>271471426 + }, + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021" + ], + "sizeBytes"=>269703297 + }, + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod03262021" + ], + "sizeBytes"=>264732875 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.19.0" + ], + "sizeBytes"=>166352383 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210623.2" + ], + "sizeBytes"=>147750148 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210524.1" + ], + "sizeBytes"=>146446618 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210427.1" + ], + "sizeBytes"=>136242776 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.8.9.5" + ], + "sizeBytes"=>101794833 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.47.0" + ], + "sizeBytes"=>101445696 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/autoscaler/cluster-proportional-autoscaler:1.3.0_v0.0.5" + ], + "sizeBytes"=>101194562 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210623.2" + ], + "sizeBytes"=>96125176 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210524.1" + ], + "sizeBytes"=>95879501 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/exechealthz:1.2_v0.0.5" + ], + "sizeBytes"=>94348102 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.8.9.2" + ], + "sizeBytes"=>93537927 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/acc/sgx-attestation:2.0" + ], + "sizeBytes"=>91841669 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.4.0" + ], + "sizeBytes"=>91324193 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.2.0" + ], + "sizeBytes"=>89103171 + }, + { + "names"=>[ + "mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.0.1-rc3" + ], + "sizeBytes"=>86839805 + }, + { + "names"=>[ + "mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.2.0" + ], + "sizeBytes"=>86488586 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210427.1" + ], + "sizeBytes"=>86120048 + }, + { + "names"=>[ + "mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.3.0" + ], + "sizeBytes"=>81252495 + }, + { + "names"=>[ + "mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.4.0" + ], + "sizeBytes"=>79586703 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.4.0" + ], + "sizeBytes"=>78795016 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.2.0" + ], + "sizeBytes"=>76527179 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.1.8" + ], + "sizeBytes"=>75025803 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.2.2_hotfix" + ], + "sizeBytes"=>73533889 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.3.1" + ], + "sizeBytes"=>72242894 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.2.8" + ], + "sizeBytes"=>70622822 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/nvidia/k8s-device-plugin:v0.9.0" + ], + "sizeBytes"=>67291599 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.1" + ], + "sizeBytes"=>66415836 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc7" + ], + "sizeBytes"=>65965658 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.2.1" + ], + "sizeBytes"=>64123775 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/cni:v3.8.9.3" + ], + "sizeBytes"=>63581323 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8" + ], + "sizeBytes"=>63154716 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/cni:v3.8.9.2" + ], + "sizeBytes"=>61626312 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.18.1" + ], + "sizeBytes"=>60500885 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.17.2" + ], + "sizeBytes"=>58419768 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8_hotfix", + "mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8post2" + ], + "sizeBytes"=>56368756 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:282543237a1aa3f407656290f454b7068a92e1abe2156082c750d5abfbcad90c", + "mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.2" + ], + "sizeBytes"=>56310724 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.19.0" + ], + "sizeBytes"=>55228749 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.1" + ], + "sizeBytes"=>54692048 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc3" + ], + "sizeBytes"=>50803639 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.19" + ], + "sizeBytes"=>49759361 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.5" + ], + "sizeBytes"=>49704644 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.21" + ], + "sizeBytes"=>49372390 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:a64d3538b72905b07356881314755b02db3675ff47ee2bcc49dd7be856e285d5", + "mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526" + ], + "sizeBytes"=>49322942 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.4" + ], + "sizeBytes"=>48108311 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/kubernetes-dashboard:v1.10.1" + ], + "sizeBytes"=>44907744 + } + ], + "config"=>{} + } + } + ] +} \ No newline at end of file From 8b970ef8cf60e24b9ce4390f93ec19735f85df0c Mon Sep 17 00:00:00 2001 From: David Michelman Date: Tue, 17 Aug 2021 16:47:39 -0700 Subject: [PATCH 20/33] test of malformed node fix done, ready to polish and write documentation --- source/plugins/ruby/in_kube_nodes.rb | 48 +- source/plugins/ruby/in_kube_nodes_test.rb | 60 +- .../kube-nodes-malformed.txt | 856 +++++++++++++++++- test/unit-tests/run_ruby_tests.sh | 1 + 4 files changed, 915 insertions(+), 50 deletions(-) diff --git a/source/plugins/ruby/in_kube_nodes.rb b/source/plugins/ruby/in_kube_nodes.rb index 35c8828eb..0ef80a79e 100644 --- a/source/plugins/ruby/in_kube_nodes.rb +++ b/source/plugins/ruby/in_kube_nodes.rb @@ -354,35 +354,35 @@ def parse_and_emit_records(nodeInventory, batchTime = Time.utc.iso8601) end ApplicationInsightsUtility.sendMetricTelemetry("NodeCoreCapacity", capacityInfo["cpu"], properties) telemetrySent = true + + # Telemetry for data collection config for replicaset + if (File.file?(@@configMapMountPath)) + properties["collectAllKubeEvents"] = @@collectAllKubeEvents + end + + #telemetry about prometheus metric collections settings for replicaset + if (File.file?(@@promConfigMountPath)) + properties["rsPromInt"] = @@rsPromInterval + properties["rsPromFPC"] = @@rsPromFieldPassCount + properties["rsPromFDC"] = @@rsPromFieldDropCount + properties["rsPromServ"] = @@rsPromK8sServiceCount + properties["rsPromUrl"] = @@rsPromUrlCount + properties["rsPromMonPods"] = @@rsPromMonitorPods + properties["rsPromMonPodsNs"] = @@rsPromMonitorPodsNamespaceLength + properties["rsPromMonPodsLabelSelectorLength"] = @@rsPromMonitorPodsLabelSelectorLength + properties["rsPromMonPodsFieldSelectorLength"] = @@rsPromMonitorPodsFieldSelectorLength + end + # telemetry about osm metric settings for replicaset + if (File.file?(@@osmConfigMountPath)) + properties["osmNamespaceCount"] = @@osmNamespaceCount + end + @applicationInsightsUtility.sendMetricTelemetry("NodeCoreCapacity", capacityInfo["cpu"], properties) + telemetrySent = true rescue => errorStr $log.warn "Failed in getting telemetry in_kube_nodes : #{errorStr}" $log.debug_backtrace(errorStr.backtrace) @applicationInsightsUtility.sendExceptionTelemetry(errorStr) end - - # Telemetry for data collection config for replicaset - if (File.file?(@@configMapMountPath)) - properties["collectAllKubeEvents"] = @@collectAllKubeEvents - end - - #telemetry about prometheus metric collections settings for replicaset - if (File.file?(@@promConfigMountPath)) - properties["rsPromInt"] = @@rsPromInterval - properties["rsPromFPC"] = @@rsPromFieldPassCount - properties["rsPromFDC"] = @@rsPromFieldDropCount - properties["rsPromServ"] = @@rsPromK8sServiceCount - properties["rsPromUrl"] = @@rsPromUrlCount - properties["rsPromMonPods"] = @@rsPromMonitorPods - properties["rsPromMonPodsNs"] = @@rsPromMonitorPodsNamespaceLength - properties["rsPromMonPodsLabelSelectorLength"] = @@rsPromMonitorPodsLabelSelectorLength - properties["rsPromMonPodsFieldSelectorLength"] = @@rsPromMonitorPodsFieldSelectorLength - end - # telemetry about osm metric settings for replicaset - if (File.file?(@@osmConfigMountPath)) - properties["osmNamespaceCount"] = @@osmNamespaceCount - end - @applicationInsightsUtility.sendMetricTelemetry("NodeCoreCapacity", capacityInfo["cpu"], properties) - telemetrySent = true end end if telemetrySent == true diff --git a/source/plugins/ruby/in_kube_nodes_test.rb b/source/plugins/ruby/in_kube_nodes_test.rb index 6d1ea5610..c7f5cd7ec 100644 --- a/source/plugins/ruby/in_kube_nodes_test.rb +++ b/source/plugins/ruby/in_kube_nodes_test.rb @@ -72,15 +72,20 @@ def extensionUtils.isAADMSIAuthMode ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"cpuCapacityNanoCores\",\"Value\":2000000000.0}]"})] => true, ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"memoryCapacityBytes\",\"Value\":7291510784.0}]"})] => true} + #TODO: remove records from expected_responses as they are recieved (to make sure that they are all recieved exactly once) d.events.each do |tag, time, record| cleaned_record = overwrite_collection_time record if expected_responses.key?([tag, cleaned_record]) - assert_equal(true, true) + expected_responses[[tag, cleaned_record]] = true else assert_equal(true, false) end end + expected_responses.each do |key, val| + assert(val, "expected record not emitted: #{key}") + end + kubeApiClient.verify appInsightsUtil.verify extensionUtils.verify @@ -104,44 +109,61 @@ def extensionUtils.isAADMSIAuthMode false end - nodes_api_response = eval(File.open("../../../test/unit-tests/canned-api-responses/kube-nodes-malformed.txt").read) + nodes_api_response = eval(File.open("../../../test/unit-tests/canned-api-responses/kube-nodes-malformed.json").read) kubeApiClient.expect(:getResourcesAndContinuationToken, [nil, nodes_api_response], ["nodes?limit=200"]) kubeApiClient.expect(:getClusterName, "/cluster-name") + kubeApiClient.expect(:getClusterName, "/cluster-name") + kubeApiClient.expect(:getClusterId, "/cluster-id") kubeApiClient.expect(:getClusterId, "/cluster-id") + def appInsightsUtil.sendExceptionTelemetry(exception) + if exception.to_s != "undefined method `[]' for nil:NilClass" + raise "an unexpected exception has occured" + end + end + + # This test doesn't care if metric telemetry is sent properly. Looking for an unnecessary value would make it needlessly rigid + def appInsightsUtil.sendMetricTelemetry(a, b, c) + end + config = "run_interval 999999999" # only run once d = create_driver(config, kubernetesApiClient=kubeApiClient, applicationInsightsUtility=appInsightsUtil, extensionUtils=extensionUtils, env=env) d.instance.start d.instance.set_telemetry_flush_interval(0) - - byebug d.instance.enumerate - d.run(timeout: 99999) # Input plugins decide when to run, so we have to give it enough time to run - - - expected_responses = { ["oneagent.containerInsights.KUBE_NODE_INVENTORY_BLOB", overwrite_collection_time({"CollectionTime"=>"2021-08-17T20:24:18Z", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"aks-nodepool1-24816391-vmss000000", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"})] => true, - ["mdm.kubenodeinventory", overwrite_collection_time({"CollectionTime"=>"2021-08-17T20:24:18Z", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"aks-nodepool1-24816391-vmss000000", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"})] => true, - ["oneagent.containerInsights.CONTAINER_NODE_INVENTORY_BLOB", overwrite_collection_time({"CollectionTime"=>"2021-08-17T20:24:18Z", "Computer"=>"aks-nodepool1-24816391-vmss000000", "OperatingSystem"=>"Ubuntu 18.04.5 LTS", "DockerVersion"=>"containerd://1.4.4+azure"})] => true, - ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"cpuAllocatableNanoCores\",\"Value\":1900000000.0}]"})] => true, - ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"memoryAllocatableBytes\",\"Value\":4787511296.0}]"})] => true, - ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"cpuCapacityNanoCores\",\"Value\":2000000000.0}]"})] => true, - ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"memoryCapacityBytes\",\"Value\":7291510784.0}]"})] => true} + d.run(timeout: 99999) #TODO: is this necessary? + + expected_responses = { + ["oneagent.containerInsights.KUBE_NODE_INVENTORY_BLOB", {"CollectionTime"=>"~CollectionTime~", "Computer"=>"correct-node", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"correct-node", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"}] => false, + ["mdm.kubenodeinventory", {"CollectionTime"=>"~CollectionTime~", "Computer"=>"correct-node", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"correct-node", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"}] => false, + ["oneagent.containerInsights.CONTAINER_NODE_INVENTORY_BLOB", {"CollectionTime"=>"~CollectionTime~", "Computer"=>"correct-node", "OperatingSystem"=>"Ubuntu 18.04.5 LTS", "DockerVersion"=>"containerd://1.4.4+azure"}] => false, + ["oneagent.containerInsights.LINUX_PERF_BLOB", {"Timestamp"=>"~Timestamp~", "Host"=>"correct-node", "Computer"=>"correct-node", "ObjectName"=>"K8SNode", "InstanceName"=>"None/correct-node", "json_Collections"=>"[{\"CounterName\":\"cpuAllocatableNanoCores\",\"Value\":1000000.0}]"}] => false, + ["oneagent.containerInsights.LINUX_PERF_BLOB", {"Timestamp"=>"~Timestamp~", "Host"=>"correct-node", "Computer"=>"correct-node", "ObjectName"=>"K8SNode", "InstanceName"=>"None/correct-node", "json_Collections"=>"[{\"CounterName\":\"memoryAllocatableBytes\",\"Value\":444.0}]"}] => false, + ["oneagent.containerInsights.LINUX_PERF_BLOB", {"Timestamp"=>"~Timestamp~", "Host"=>"correct-node", "Computer"=>"correct-node", "ObjectName"=>"K8SNode", "InstanceName"=>"None/correct-node", "json_Collections"=>"[{\"CounterName\":\"cpuCapacityNanoCores\",\"Value\":2000000.0}]"}] => false, + ["oneagent.containerInsights.LINUX_PERF_BLOB", {"Timestamp"=>"~Timestamp~", "Host"=>"correct-node", "Computer"=>"correct-node", "ObjectName"=>"K8SNode", "InstanceName"=>"None/correct-node", "json_Collections"=>"[{\"CounterName\":\"memoryCapacityBytes\",\"Value\":555.0}]"}] => false, + + ["oneagent.containerInsights.KUBE_NODE_INVENTORY_BLOB", {"CollectionTime"=>"~CollectionTime~", "Computer"=>"malformed-node", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"malformed-node", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"}] => false, + ["mdm.kubenodeinventory", {"CollectionTime"=>"~CollectionTime~", "Computer"=>"malformed-node", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"malformed-node", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"}] => false, + ["oneagent.containerInsights.CONTAINER_NODE_INVENTORY_BLOB", {"CollectionTime"=>"~CollectionTime~", "Computer"=>"malformed-node", "OperatingSystem"=>"Ubuntu 18.04.5 LTS", "DockerVersion"=>"containerd://1.4.4+azure"}] => false + } d.events.each do |tag, time, record| cleaned_record = overwrite_collection_time record if expected_responses.key?([tag, cleaned_record]) - assert_equal(true, true) - else - assert_equal(true, false) + expected_responses[[tag, cleaned_record]] = true end + # don't do anything if an unexpected record was emitted. Since the node spec is malformed, there will be some partial data. + # we care more that the non-malformed data is still emitted + end + + expected_responses.each do |key, val| + assert(val, "expected record not emitted: #{key}") end kubeApiClient.verify appInsightsUtil.verify extensionUtils.verify end - - end diff --git a/test/unit-tests/canned-api-responses/kube-nodes-malformed.txt b/test/unit-tests/canned-api-responses/kube-nodes-malformed.txt index 9aa10b6f1..bb4c61ca5 100644 --- a/test/unit-tests/canned-api-responses/kube-nodes-malformed.txt +++ b/test/unit-tests/canned-api-responses/kube-nodes-malformed.txt @@ -8,8 +8,8 @@ "items"=>[ { "metadata"=>{ - "name"=>"aks-nodepool1-24816391-vmss000000", - "selfLink"=>"/api/v1/nodes/aks-nodepool1-24816391-vmss000000", + "name"=>"malformed-node", + "selfLink"=>"/api/v1/nodes/malformed-node", "uid"=>"fe073f0a-e6bf-4d68-b4e5-ffaa42b91528", "resourceVersion"=>"5974522", "creationTimestamp"=>"2021-07-21T23:40:14Z", @@ -26,7 +26,7 @@ "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", - "kubernetes.io/hostname"=>"aks-nodepool1-24816391-vmss000000", + "kubernetes.io/hostname"=>"malformed-node", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", @@ -117,6 +117,839 @@ "f:memory"=>{}, "f:pods"=>{} }, + "f:capacity"=>{ + "."=>{}, + "f:attachable-volumes-azure-disk"=>{}, + "f:cpu"=>{}, + "f:ephemeral-storage"=>{}, + "f:hugepages-1Gi"=>{}, + "f:hugepages-2Mi"=>{}, + "f:memory"=>{}, + "f:pods"=>{} + }, + "f:conditions"=>{ + "."=>{}, + "k:{\"type\":\"DiskPressure\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"MemoryPressure\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"PIDPressure\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"Ready\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + } + }, + "f:config"=>{}, + "f:daemonEndpoints"=>{ + "f:kubeletEndpoint"=>{ + "f:Port"=>{} + } + }, + "f:images"=>{}, + "f:nodeInfo"=>{ + "f:architecture"=>{}, + "f:bootID"=>{}, + "f:containerRuntimeVersion"=>{}, + "f:kernelVersion"=>{}, + "f:kubeProxyVersion"=>{}, + "f:kubeletVersion"=>{}, + "f:machineID"=>{}, + "f:operatingSystem"=>{}, + "f:osImage"=>{}, + "f:systemUUID"=>{} + } + } + } + }, + { + "manager"=>"kubectl-label", + "operation"=>"Update", + "apiVersion"=>"v1", + "time"=>"2021-07-21T23:40:53Z", + "fieldsType"=>"FieldsV1", + "fieldsV1"=>{ + "f:metadata"=>{ + "f:labels"=>{ + "f:kubernetes.io/role"=>{}, + "f:node-role.kubernetes.io/agent"=>{} + } + } + } + }, + { + "manager"=>"node-problem-detector", + "operation"=>"Update", + "apiVersion"=>"v1", + "time"=>"2021-08-10T18:10:02Z", + "fieldsType"=>"FieldsV1", + "fieldsV1"=>{ + "f:status"=>{ + "f:conditions"=>{ + "k:{\"type\":\"ContainerRuntimeProblem\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FilesystemCorruptionProblem\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FreezeScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FrequentContainerdRestart\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FrequentDockerRestart\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FrequentKubeletRestart\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"FrequentUnregisterNetDevice\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"KernelDeadlock\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"KubeletProblem\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"PreemptScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"ReadonlyFilesystem\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"RebootScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"RedeployScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"TerminateScheduled\"}"=>{ + "."=>{}, + "f:lastHeartbeatTime"=>{}, + "f:lastTransitionTime"=>{}, + "f:message"=>{}, + "f:reason"=>{}, + "f:status"=>{}, + "f:type"=>{} + } + } + } + } + } + ] + }, + "spec"=>{ + "providerID"=>"azure:///subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/mc_davidaks16_davidaks16_westus2/providers/Microsoft.Compute/virtualMachineScaleSets/aks-nodepool1-24816391-vmss/virtualMachines/0" + }, + "status"=>{ + "conditions"=>[ + { + "type"=>"FrequentDockerRestart", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoFrequentDockerRestart", + "message"=>"docker is functioning properly" + }, + { + "type"=>"FilesystemCorruptionProblem", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"FilesystemIsOK", + "message"=>"Filesystem is healthy" + }, + { + "type"=>"KernelDeadlock", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"KernelHasNoDeadlock", + "message"=>"kernel has no deadlock" + }, + { + "type"=>"FrequentContainerdRestart", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoFrequentContainerdRestart", + "message"=>"containerd is functioning properly" + }, + { + "type"=>"FreezeScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-11T23:25:04Z", + "reason"=>"NoFreezeScheduled", + "message"=>"VM has no scheduled Freeze event" + }, + { + "type"=>"FrequentUnregisterNetDevice", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoFrequentUnregisterNetDevice", + "message"=>"node is functioning properly" + }, + { + "type"=>"TerminateScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoTerminateScheduled", + "message"=>"VM has no scheduled Terminate event" + }, + { + "type"=>"ReadonlyFilesystem", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"FilesystemIsNotReadOnly", + "message"=>"Filesystem is not read-only" + }, + { + "type"=>"RedeployScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoRedeployScheduled", + "message"=>"VM has no scheduled Redeploy event" + }, + { + "type"=>"KubeletProblem", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"KubeletIsUp", + "message"=>"kubelet service is up" + }, + { + "type"=>"PreemptScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:11:11Z", + "reason"=>"NoPreemptScheduled", + "message"=>"VM has no scheduled Preempt event" + }, + { + "type"=>"RebootScheduled", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoRebootScheduled", + "message"=>"VM has no scheduled Reboot event" + }, + { + "type"=>"ContainerRuntimeProblem", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"ContainerRuntimeIsUp", + "message"=>"container runtime service is up" + }, + { + "type"=>"FrequentKubeletRestart", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:25:56Z", + "lastTransitionTime"=>"2021-08-10T18:10:01Z", + "reason"=>"NoFrequentKubeletRestart", + "message"=>"kubelet is functioning properly" + }, + { + "type"=>"MemoryPressure", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:28:21Z", + "lastTransitionTime"=>"2021-07-21T23:40:14Z", + "reason"=>"KubeletHasSufficientMemory", + "message"=>"kubelet has sufficient memory available" + }, + { + "type"=>"DiskPressure", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:28:21Z", + "lastTransitionTime"=>"2021-07-21T23:40:14Z", + "reason"=>"KubeletHasNoDiskPressure", + "message"=>"kubelet has no disk pressure" + }, + { + "type"=>"PIDPressure", + "status"=>"False", + "lastHeartbeatTime"=>"2021-08-17T19:28:21Z", + "lastTransitionTime"=>"2021-07-21T23:40:14Z", + "reason"=>"KubeletHasSufficientPID", + "message"=>"kubelet has sufficient PID available" + }, + { + "type"=>"Ready", + "status"=>"True", + "lastHeartbeatTime"=>"2021-08-17T19:28:21Z", + "lastTransitionTime"=>"2021-07-21T23:40:24Z", + "reason"=>"KubeletReady", + "message"=>"kubelet is posting ready status. AppArmor enabled" + } + ], + "addresses"=>[ + { + "type"=>"Hostname", + "address"=>"malformed-node" + }, + { + "type"=>"InternalIP", + "address"=>"10.240.0.4" + } + ], + "daemonEndpoints"=>{ + "kubeletEndpoint"=>{ + "Port"=>10250 + } + }, + "nodeInfo"=>{ + "machineID"=>"17a654260e2c4a9bb3a3eb4b4188e4b4", + "systemUUID"=>"7ff599e4-909e-4950-a044-ff8613af3af9", + "bootID"=>"02bb865b-a469-43cd-8b0b-5ceb4ecd80b0", + "kernelVersion"=>"5.4.0-1051-azure", + "osImage"=>"Ubuntu 18.04.5 LTS", + "containerRuntimeVersion"=>"containerd://1.4.4+azure", + "kubeletVersion"=>"v1.19.11", + "kubeProxyVersion"=>"v1.19.11", + "operatingSystem"=>"linux", + "architecture"=>"amd64" + }, + "images"=>[ + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021-1" + ], + "sizeBytes"=>331689060 + }, + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021" + ], + "sizeBytes"=>330099815 + }, + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021-hotfix" + ], + "sizeBytes"=>271471426 + }, + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021" + ], + "sizeBytes"=>269703297 + }, + { + "names"=>[ + "mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod03262021" + ], + "sizeBytes"=>264732875 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.19.0" + ], + "sizeBytes"=>166352383 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210623.2" + ], + "sizeBytes"=>147750148 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210524.1" + ], + "sizeBytes"=>146446618 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210427.1" + ], + "sizeBytes"=>136242776 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.8.9.5" + ], + "sizeBytes"=>101794833 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.47.0" + ], + "sizeBytes"=>101445696 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/autoscaler/cluster-proportional-autoscaler:1.3.0_v0.0.5" + ], + "sizeBytes"=>101194562 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210623.2" + ], + "sizeBytes"=>96125176 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210524.1" + ], + "sizeBytes"=>95879501 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/exechealthz:1.2_v0.0.5" + ], + "sizeBytes"=>94348102 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.8.9.2" + ], + "sizeBytes"=>93537927 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/acc/sgx-attestation:2.0" + ], + "sizeBytes"=>91841669 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.4.0" + ], + "sizeBytes"=>91324193 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.2.0" + ], + "sizeBytes"=>89103171 + }, + { + "names"=>[ + "mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.0.1-rc3" + ], + "sizeBytes"=>86839805 + }, + { + "names"=>[ + "mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.2.0" + ], + "sizeBytes"=>86488586 + }, + { + "names"=>[ + "mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210427.1" + ], + "sizeBytes"=>86120048 + }, + { + "names"=>[ + "mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.3.0" + ], + "sizeBytes"=>81252495 + }, + { + "names"=>[ + "mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.4.0" + ], + "sizeBytes"=>79586703 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.4.0" + ], + "sizeBytes"=>78795016 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.2.0" + ], + "sizeBytes"=>76527179 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.1.8" + ], + "sizeBytes"=>75025803 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.2.2_hotfix" + ], + "sizeBytes"=>73533889 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.3.1" + ], + "sizeBytes"=>72242894 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.2.8" + ], + "sizeBytes"=>70622822 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/nvidia/k8s-device-plugin:v0.9.0" + ], + "sizeBytes"=>67291599 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.1" + ], + "sizeBytes"=>66415836 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc7" + ], + "sizeBytes"=>65965658 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/azure-npm:v1.2.1" + ], + "sizeBytes"=>64123775 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/cni:v3.8.9.3" + ], + "sizeBytes"=>63581323 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8" + ], + "sizeBytes"=>63154716 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/cni:v3.8.9.2" + ], + "sizeBytes"=>61626312 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.18.1" + ], + "sizeBytes"=>60500885 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.17.2" + ], + "sizeBytes"=>58419768 + }, + { + "names"=>[ + "mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8_hotfix", + "mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8post2" + ], + "sizeBytes"=>56368756 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:282543237a1aa3f407656290f454b7068a92e1abe2156082c750d5abfbcad90c", + "mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.2" + ], + "sizeBytes"=>56310724 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/calico/node:v3.19.0" + ], + "sizeBytes"=>55228749 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.1" + ], + "sizeBytes"=>54692048 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc3" + ], + "sizeBytes"=>50803639 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.19" + ], + "sizeBytes"=>49759361 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.5" + ], + "sizeBytes"=>49704644 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.21" + ], + "sizeBytes"=>49372390 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:a64d3538b72905b07356881314755b02db3675ff47ee2bcc49dd7be856e285d5", + "mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526" + ], + "sizeBytes"=>49322942 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.4" + ], + "sizeBytes"=>48108311 + }, + { + "names"=>[ + "mcr.microsoft.com/oss/kubernetes/kubernetes-dashboard:v1.10.1" + ], + "sizeBytes"=>44907744 + } + ], + "config"=>{} + } + }, + { + "metadata"=>{ + "name"=>"correct-node", + "selfLink"=>"/api/v1/nodes/correct-node", + "uid"=>"fe073f0a-e6bf-4d68-b4e5-ffaa42b91528", + "resourceVersion"=>"5974522", + "creationTimestamp"=>"2021-07-21T23:40:14Z", + "labels"=>{ + "agentpool"=>"nodepool1", + "beta.kubernetes.io/arch"=>"amd64", + "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", + "beta.kubernetes.io/os"=>"linux", + "failure-domain.beta.kubernetes.io/region"=>"westus2", + "failure-domain.beta.kubernetes.io/zone"=>"0", + "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", + "kubernetes.azure.com/mode"=>"system", + "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", + "kubernetes.azure.com/os-sku"=>"Ubuntu", + "kubernetes.azure.com/role"=>"agent", + "kubernetes.io/arch"=>"amd64", + "kubernetes.io/hostname"=>"correct-node", + "kubernetes.io/os"=>"linux", + "kubernetes.io/role"=>"agent", + "node-role.kubernetes.io/agent"=>"", + "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", + "storageprofile"=>"managed", + "storagetier"=>"Premium_LRS", + "topology.kubernetes.io/region"=>"westus2", + "topology.kubernetes.io/zone"=>"0" + }, + "annotations"=>{ + "node.alpha.kubernetes.io/ttl"=>"0", + "volumes.kubernetes.io/controller-managed-attach-detach"=>"true" + }, + "managedFields"=>[ + { + "manager"=>"kube-controller-manager", + "operation"=>"Update", + "apiVersion"=>"v1", + "time"=>"2021-07-21T23:40:20Z", + "fieldsType"=>"FieldsV1", + "fieldsV1"=>{ + "f:metadata"=>{ + "f:annotations"=>{ + "f:node.alpha.kubernetes.io/ttl"=>{} + } + } + } + }, + { + "manager"=>"kubelet", + "operation"=>"Update", + "apiVersion"=>"v1", + "time"=>"2021-07-21T23:40:24Z", + "fieldsType"=>"FieldsV1", + "fieldsV1"=>{ + "f:metadata"=>{ + "f:annotations"=>{ + "."=>{}, + "f:volumes.kubernetes.io/controller-managed-attach-detach"=>{} + }, + "f:labels"=>{ + "."=>{}, + "f:agentpool"=>{}, + "f:beta.kubernetes.io/arch"=>{}, + "f:beta.kubernetes.io/instance-type"=>{}, + "f:beta.kubernetes.io/os"=>{}, + "f:failure-domain.beta.kubernetes.io/region"=>{}, + "f:failure-domain.beta.kubernetes.io/zone"=>{}, + "f:kubernetes.azure.com/cluster"=>{}, + "f:kubernetes.azure.com/mode"=>{}, + "f:kubernetes.azure.com/node-image-version"=>{}, + "f:kubernetes.azure.com/os-sku"=>{}, + "f:kubernetes.azure.com/role"=>{}, + "f:kubernetes.io/arch"=>{}, + "f:kubernetes.io/hostname"=>{}, + "f:kubernetes.io/os"=>{}, + "f:node.kubernetes.io/instance-type"=>{}, + "f:storageprofile"=>{}, + "f:storagetier"=>{}, + "f:topology.kubernetes.io/region"=>{}, + "f:topology.kubernetes.io/zone"=>{} + } + }, + "f:spec"=>{ + "f:providerID"=>{} + }, + "f:status"=>{ + "f:addresses"=>{ + "."=>{}, + "k:{\"type\":\"Hostname\"}"=>{ + "."=>{}, + "f:address"=>{}, + "f:type"=>{} + }, + "k:{\"type\":\"InternalIP\"}"=>{ + "."=>{}, + "f:address"=>{}, + "f:type"=>{} + } + }, + "f:allocatable"=>{ + "."=>{}, + "f:attachable-volumes-azure-disk"=>{}, + "f:cpu"=>{}, + "f:ephemeral-storage"=>{}, + "f:hugepages-1Gi"=>{}, + "f:hugepages-2Mi"=>{}, + "f:memory"=>{}, + "f:pods"=>{} + }, + "f:capacity"=>{ + "."=>{}, + "f:attachable-volumes-azure-disk"=>{}, + "f:cpu"=>{}, + "f:ephemeral-storage"=>{}, + "f:hugepages-1Gi"=>{}, + "f:hugepages-2Mi"=>{}, + "f:memory"=>{}, + "f:pods"=>{} + }, "f:conditions"=>{ "."=>{}, "k:{\"type\":\"DiskPressure\"}"=>{ @@ -338,13 +1171,22 @@ "providerID"=>"azure:///subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/mc_davidaks16_davidaks16_westus2/providers/Microsoft.Compute/virtualMachineScaleSets/aks-nodepool1-24816391-vmss/virtualMachines/0" }, "status"=>{ + "capacity"=>{ + "attachable-volumes-azure-disk"=>"8", + "cpu"=>"2m", + "ephemeral-storage"=>"666", + "hugepages-1Gi"=>"0", + "hugepages-2Mi"=>"0", + "memory"=>"555", + "pods"=>"30" + }, "allocatable"=>{ "attachable-volumes-azure-disk"=>"8", - "cpu"=>"1900m", - "ephemeral-storage"=>"119716326407", + "cpu"=>"1m", + "ephemeral-storage"=>"333", "hugepages-1Gi"=>"0", "hugepages-2Mi"=>"0", - "memory"=>"4675304Ki", + "memory"=>"444", "pods"=>"30" }, "conditions"=>[ @@ -496,7 +1338,7 @@ "addresses"=>[ { "type"=>"Hostname", - "address"=>"aks-nodepool1-24816391-vmss000000" + "address"=>"correct-node" }, { "type"=>"InternalIP", diff --git a/test/unit-tests/run_ruby_tests.sh b/test/unit-tests/run_ruby_tests.sh index efc35890b..7d1f4bc03 100755 --- a/test/unit-tests/run_ruby_tests.sh +++ b/test/unit-tests/run_ruby_tests.sh @@ -1,3 +1,4 @@ +#TODO: add support for running a single specific test OLD_PATH=$(pwd) SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" From 7690d6b7ec07dfd98ee5cef8b5678ea46885b23e Mon Sep 17 00:00:00 2001 From: David Michelman Date: Tue, 17 Aug 2021 17:40:19 -0700 Subject: [PATCH 21/33] some documentation --- .gitignore | 1 + Dev Guide.md | 117 +++++++++++++++++ .../go/src/extension/extension_test.go | 27 ---- .../go/src/extension/mock_socket_writer.go | 122 ------------------ .../plugins/go/src/extension/socket_writer.go | 2 +- source/plugins/ruby/filter_cadvisor2mdm.rb | 4 - .../plugins/ruby/filter_cadvisor2mdm_test.rb | 2 +- source/plugins/ruby/in_kube_nodes.rb | 1 + source/plugins/ruby/in_kube_nodes_test.rb | 8 +- test/unit-tests/run_go_tests.sh | 1 + 10 files changed, 128 insertions(+), 157 deletions(-) create mode 100644 Dev Guide.md delete mode 100644 source/plugins/go/src/extension/mock_socket_writer.go diff --git a/.gitignore b/.gitignore index 2e2978e91..9cd873ce1 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ intermediate kubernetes/linux/Linux_ULINUX_1.0_x64_64_Release # ignore generated .h files for go source/plugins/go/src/*.h +*_mock.go \ No newline at end of file diff --git a/Dev Guide.md b/Dev Guide.md new file mode 100644 index 000000000..18596f2b6 --- /dev/null +++ b/Dev Guide.md @@ -0,0 +1,117 @@ +# Dev Guide + +More advanced information needed to develop or build the docker provider will live here + + + +## Testing +Last updated 8/18/2021 + +To run all unit tests run the commands `test/unit-tests/run_go_tests.sh` and `test/unit-tests/run_ruby_tests.sh` + +#### Conventions: +1. Unit tests should go in their own file, but in the same folder as the source code their testing. For example, the tests for `in_kube_nodes.rb` are in `in_kube_nodes_test.rb`. Both files are in the folder `source/plugin/ruby`. + +### Ruby +Sample tests are provided in [in_kube_nodes_test.rb](source/plugin/ruby/in_kube_nodes_test.rb) and [filter_cadvisor2mdm_test.rb](source/plugin/ruby/filter_cadvisor2mdm_test.rb). They are meant to demo the tooling used for unit tests (as opposed to being comprehensive tests). Basic techniques like mocking are demonstrated there. + +#### Conventions: +1. When modifying a fluentd plugin for unit testing, any mocked classes (like KubernetesApiClient, applicationInsightsUtility, env, etc.) should be passed in as optional arguments of initialize. For example: +``` + def initialize + super +``` +would be turned into +``` + def initialize (kubernetesApiClient=nil, applicationInsightsUtility=nil, extensionUtils=nil, env=nil) + super() +``` + +2. Having end-to-end tests of all fluentd plugins is a longshot. We care more about unit testing smaller blocks of functionality (like all the helper functions in KubeNodeInventory.rb). Unit tests for fluentd plugins are not expected. + +### Golang + +Since golang is statically compiled, mocking requires a lot more work than in ruby. Sample tests are provided in [utils_test.go](source/plugin/go/src/utils_test.go) and [extension_test.go](source/plugin/go/src/extension/extension_test.go). Again, they are meant to demo the tooling used for unit tests (as opposed to being comprehensive tests). Basic techniques like mocking are demonstrated there. + +#### Mocking: +Mocks are generated with gomock (mockgen). +* Mock files should be called *_mock.go (socket_writer.go => socket_writer_mock.go) +* Mocks should not be checked in to git. (they have been added to the .gitignore) +* The command to generate mock files should go in a `//go:generate` comment at the top of the mocked file (see [socket_writer.go](source/plugin/go/src/extension/socket_writer.go) for an example). This way mocks can be generated by the unit test script. +* Mocks also go in the same folder as the mocked files. This is unfortunate, but necessary to avoid circular package dependencies (anyone else feel free to figure out how to move mocks to a separate folder) + +Using mocks is also a little tricky. In order to mock functions in a package, they must be converted to reciever methods of a struct. This way the struct can be swapped out at runtime to change which implementaions of a method are called. See the example below: + +``` +// declare all functions to be mocked in this interface +type registrationPreCheckerInterface interface { + FUT(string) bool +} + +// Create a struct which implements the above interface +type regPreCheck struct{} + +func (r regPreCheck) FUT(email string) bool { + fmt.Println("real FUT() called") + return true +} + +// Create a global variable and assign it to the struct +var regPreCondVar registrationPreCheckerInterface + +func init() { + regPreCondVar = regPreCheck{} +} +``` + +Now any code wishing to call FUT() will call `regPreCondVar.FUT("")` + +A unit test can substitute its own implementaion of FUT() like so + +``` +// This will hold the mock of FUT we want to substitute +var FUTMock func(email string) bool + +// create a new struct which implements the earlier interface +type regPreCheckMock struct{} + +func (u regPreCheckMock) FUT(email string) bool { + return FUTMock(email) +} +``` + +Everything is set up. Now a unit test can substitute in a mock like so: + +``` +func someUnitTest() { + // This will call the actual implementaion of FUT() + regPreCondVar.FUT("") + + // Now the test creates another struct to substitue. After this like all calls to FUT() will be diverted + regPreCondVar = regPreCheckMock{} + + // substute another function to run instead of FUT() + FUTMock = func(email string) bool { + fmt.Println("FUT 1 called") + return false + } + // This will call the function defined right above + regPreCondVar.FUT("") + + // We can substitue another implementation + FUTMock = func(email string) bool { + fmt.Println("FUT 2 called") + return false + } + regPreCondVar.FUT("") + + // put the old behavior back + regPreCondVar = regPreCheck{} + // this will call the actual implementation of FUT() + regPreCondVar.FUT("") + +} +``` + +A concrete example of this can be found in [socket_writer.go](source/plugin/go/src/extension/socket_writer.go) and [extension_test.go](source/plugin/go/src/extension/extension_test.go). Again, if anybody has a better way feel free to update this guide. + diff --git a/source/plugins/go/src/extension/extension_test.go b/source/plugins/go/src/extension/extension_test.go index 3cd484700..d52e63ed9 100644 --- a/source/plugins/go/src/extension/extension_test.go +++ b/source/plugins/go/src/extension/extension_test.go @@ -10,33 +10,6 @@ import ( "github.com/golang/mock/gomock" ) -// func Test_isValidUrl(t *testing.T) { -// type test_struct struct { -// isValid bool -// url string -// } - -// tests := []test_struct{ -// {true, "https://www.microsoft.com"}, -// {true, "http://abc.xyz"}, -// {true, "https://www.microsoft.com/tests"}, -// {false, "()"}, -// {false, "https//www.microsoft.com"}, -// {false, "https:/www.microsoft.com"}, -// {false, "https:/www.microsoft.com*"}, -// {false, ""}, -// } - -// for _, tt := range tests { -// t.Run(tt.url, func(t *testing.T) { -// got := isValidUrl(tt.url) -// if got != tt.isValid { -// t.Errorf("isValidUrl(%s) = %t, want %t", tt.url, got, tt.isValid) -// } -// }) -// } -// } - type FluentSocketWriterMock struct{} func Test_getDataTypeToStreamIdMapping(t *testing.T) { diff --git a/source/plugins/go/src/extension/mock_socket_writer.go b/source/plugins/go/src/extension/mock_socket_writer.go deleted file mode 100644 index 91b86c655..000000000 --- a/source/plugins/go/src/extension/mock_socket_writer.go +++ /dev/null @@ -1,122 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: Docker-Provider/source/plugins/go/src/extension (interfaces: IFluentSocketWriter) - -// Package extension is a generated GoMock package. -package extension - -import ( - reflect "reflect" - - gomock "github.com/golang/mock/gomock" -) - -// MockIFluentSocketWriter is a mock of IFluentSocketWriter interface. -type MockIFluentSocketWriter struct { - ctrl *gomock.Controller - recorder *MockIFluentSocketWriterMockRecorder -} - -// MockIFluentSocketWriterMockRecorder is the mock recorder for MockIFluentSocketWriter. -type MockIFluentSocketWriterMockRecorder struct { - mock *MockIFluentSocketWriter -} - -// NewMockIFluentSocketWriter creates a new mock instance. -func NewMockIFluentSocketWriter(ctrl *gomock.Controller) *MockIFluentSocketWriter { - mock := &MockIFluentSocketWriter{ctrl: ctrl} - mock.recorder = &MockIFluentSocketWriterMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIFluentSocketWriter) EXPECT() *MockIFluentSocketWriterMockRecorder { - return m.recorder -} - -// Write mocks base method. -func (m *MockIFluentSocketWriter) Write(arg0 *FluentSocket, arg1 []byte) (int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Write", arg0, arg1) - ret0, _ := ret[0].(int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Write indicates an expected call of Write. -func (mr *MockIFluentSocketWriterMockRecorder) Write(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Write", reflect.TypeOf((*MockIFluentSocketWriter)(nil).Write), arg0, arg1) -} - -// WriteAndRead mocks base method. -func (m *MockIFluentSocketWriter) WriteAndRead(arg0 *FluentSocket, arg1 []byte) ([]byte, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WriteAndRead", arg0, arg1) - ret0, _ := ret[0].([]byte) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// WriteAndRead indicates an expected call of WriteAndRead. -func (mr *MockIFluentSocketWriterMockRecorder) WriteAndRead(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteAndRead", reflect.TypeOf((*MockIFluentSocketWriter)(nil).WriteAndRead), arg0, arg1) -} - -// connect mocks base method. -func (m *MockIFluentSocketWriter) connect(arg0 *FluentSocket) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "connect", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// connect indicates an expected call of connect. -func (mr *MockIFluentSocketWriterMockRecorder) connect(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "connect", reflect.TypeOf((*MockIFluentSocketWriter)(nil).connect), arg0) -} - -// disConnect mocks base method. -func (m *MockIFluentSocketWriter) disConnect(arg0 *FluentSocket) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "disConnect", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// disConnect indicates an expected call of disConnect. -func (mr *MockIFluentSocketWriterMockRecorder) disConnect(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "disConnect", reflect.TypeOf((*MockIFluentSocketWriter)(nil).disConnect), arg0) -} - -// read mocks base method. -func (m *MockIFluentSocketWriter) read(arg0 *FluentSocket) ([]byte, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "read", arg0) - ret0, _ := ret[0].([]byte) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// read indicates an expected call of read. -func (mr *MockIFluentSocketWriterMockRecorder) read(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "read", reflect.TypeOf((*MockIFluentSocketWriter)(nil).read), arg0) -} - -// writeWithRetries mocks base method. -func (m *MockIFluentSocketWriter) writeWithRetries(arg0 *FluentSocket, arg1 []byte) (int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "writeWithRetries", arg0, arg1) - ret0, _ := ret[0].(int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// writeWithRetries indicates an expected call of writeWithRetries. -func (mr *MockIFluentSocketWriterMockRecorder) writeWithRetries(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "writeWithRetries", reflect.TypeOf((*MockIFluentSocketWriter)(nil).writeWithRetries), arg0, arg1) -} diff --git a/source/plugins/go/src/extension/socket_writer.go b/source/plugins/go/src/extension/socket_writer.go index 12cf4b7f5..62a9b9fa0 100644 --- a/source/plugins/go/src/extension/socket_writer.go +++ b/source/plugins/go/src/extension/socket_writer.go @@ -4,7 +4,7 @@ import ( "net" ) -//go:generate mockgen -destination=mock_socket_writer.go -package=extension Docker-Provider/source/plugins/go/src/extension IFluentSocketWriter +//go:generate mockgen -destination=socket_writer_mock.go -package=extension Docker-Provider/source/plugins/go/src/extension IFluentSocketWriter //MaxRetries for trying to write data to the socket const MaxRetries = 5 diff --git a/source/plugins/ruby/filter_cadvisor2mdm.rb b/source/plugins/ruby/filter_cadvisor2mdm.rb index f3fe3e71e..cc95fe2ce 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm.rb @@ -13,7 +13,6 @@ module Fluent::Plugin require_relative "MdmMetricsGenerator" require_relative "in_kube_nodes" require_relative "constants" - require 'byebug' class CAdvisor2MdmFilter < Filter Fluent::Plugin.register_filter("cadvisor2mdm", self) @@ -53,7 +52,6 @@ def start(env=ENV, applicationInsightsUtility=ApplicationInsightsUtility, kubern @AplicationInsightsUtility = applicationInsightsUtility @KubernetesAPIClient = kubernetesApiClient @KubeletUtils = kubeletUtils - byebug super() @@isWindows = false @@ -360,7 +358,6 @@ def ensure_cpu_memory_capacity_and_allocatable_set @Log.info "ensure_cpu_memory_capacity_set @cpu_capacity #{@cpu_capacity} @memory_capacity #{@memory_capacity}" begin - byebug resourceUri = @KubernetesAPIClient.getNodesResourceUri("nodes?fieldSelector=metadata.name%3D#{@@hostName}") nodeInventory = JSON.parse(@KubernetesAPIClient.getKubeResourceInfo(resourceUri).body) rescue Exception => e @@ -415,7 +412,6 @@ def ensure_cpu_memory_capacity_and_allocatable_set end def filter_stream(tag, es) - byebug new_es = Fluent::MultiEventStream.new begin ensure_cpu_memory_capacity_and_allocatable_set diff --git a/source/plugins/ruby/filter_cadvisor2mdm_test.rb b/source/plugins/ruby/filter_cadvisor2mdm_test.rb index d3e398989..29c92730d 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm_test.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm_test.rb @@ -44,7 +44,7 @@ def getKubeResourceInfo(resource, api_group: nil) -class MyInputTest < Minitest::Test +class FilterCadvisor2MdmTests < Minitest::Test include Fluent::Test::Helpers def setup diff --git a/source/plugins/ruby/in_kube_nodes.rb b/source/plugins/ruby/in_kube_nodes.rb index 0ef80a79e..f69d84585 100644 --- a/source/plugins/ruby/in_kube_nodes.rb +++ b/source/plugins/ruby/in_kube_nodes.rb @@ -147,6 +147,7 @@ def enumerate # Initializing continuation token to nil continuationToken = nil $log.info("in_kube_nodes::enumerate : Getting nodes from Kube API @ #{Time.now.utc.iso8601}") + # KubernetesApiClient.getNodesResourceUri is a pure function, so call it from the actual module instead of from the mock resourceUri = KubernetesApiClient.getNodesResourceUri("nodes?limit=#{@NODES_CHUNK_SIZE}") continuationToken, nodeInventory = @kubernetesApiClient.getResourcesAndContinuationToken(resourceUri) $log.info("in_kube_nodes::enumerate : Done getting nodes from Kube API @ #{Time.now.utc.iso8601}") diff --git a/source/plugins/ruby/in_kube_nodes_test.rb b/source/plugins/ruby/in_kube_nodes_test.rb index c7f5cd7ec..f84f5fd92 100644 --- a/source/plugins/ruby/in_kube_nodes_test.rb +++ b/source/plugins/ruby/in_kube_nodes_test.rb @@ -10,7 +10,7 @@ require_relative 'in_kube_nodes.rb' require 'byebug' -class MyInputTest < Minitest::Test +class InKubeNodesTests < Minitest::Test include Fluent::Test::Helpers def setup @@ -109,7 +109,11 @@ def extensionUtils.isAADMSIAuthMode false end - nodes_api_response = eval(File.open("../../../test/unit-tests/canned-api-responses/kube-nodes-malformed.json").read) + # Set up the KubernetesApiClient Mock. Note: most of the functions in KubernetesApiClient are pure (access no + # state other than their arguments), so there is no need to mock them (this test file would be far longer and + # more brittle). Instead, in_kube_nodes bypasses the mock and directly calls these functions in KubernetesApiClient. + # Ideally the pure functions in KubernetesApiClient would be refactored into their own file. + nodes_api_response = eval(File.open("../../../test/unit-tests/canned-api-responses/kube-nodes-malformed.txt").read) kubeApiClient.expect(:getResourcesAndContinuationToken, [nil, nodes_api_response], ["nodes?limit=200"]) kubeApiClient.expect(:getClusterName, "/cluster-name") kubeApiClient.expect(:getClusterName, "/cluster-name") diff --git a/test/unit-tests/run_go_tests.sh b/test/unit-tests/run_go_tests.sh index 68fd56a69..22ab29069 100755 --- a/test/unit-tests/run_go_tests.sh +++ b/test/unit-tests/run_go_tests.sh @@ -3,6 +3,7 @@ set -e OLD_PATH=$(pwd) SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" cd $SCRIPTPATH/../../source/plugins/go/src +go generate go test . cd $OLD_PATH From b6905edd8dbd288fd974b600166ce21e72ea69a1 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Wed, 18 Aug 2021 15:04:24 -0700 Subject: [PATCH 22/33] cleanup --- .gitignore | 3 ++- build/windows/Makefile.ps1 | 8 ++++---- source/plugins/go/src/extension/extension.go | 9 +++++---- .../plugins/go/src/extension/extension_test.go | 4 ++-- source/plugins/go/src/extension/socket_writer.go | 16 ++++++++-------- source/plugins/ruby/filter_cadvisor2mdm_test.rb | 5 ----- source/plugins/ruby/in_kube_nodes_test.rb | 3 --- source/plugins/ruby/test_driver.rb | 6 ------ source/plugins/ruby/test_registry.rb | 16 ---------------- 9 files changed, 21 insertions(+), 49 deletions(-) delete mode 100644 source/plugins/ruby/test_driver.rb delete mode 100644 source/plugins/ruby/test_registry.rb diff --git a/.gitignore b/.gitignore index 9cd873ce1..9d678bbc3 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,5 @@ intermediate kubernetes/linux/Linux_ULINUX_1.0_x64_64_Release # ignore generated .h files for go source/plugins/go/src/*.h -*_mock.go \ No newline at end of file +*_mock.go +*_log.txt diff --git a/build/windows/Makefile.ps1 b/build/windows/Makefile.ps1 index 737abc92a..c8dacc06f 100644 --- a/build/windows/Makefile.ps1 +++ b/build/windows/Makefile.ps1 @@ -185,9 +185,9 @@ Write-Host("copying ruby source files from :" + $rubyplugindir + " to :" + $pu Copy-Item -Path $rubyplugindir -Destination $publishdir -Recurse -Force Write-Host("successfully copied ruby source files from :" + $rubyplugindir + " to :" + $publishdir + " ") -ForegroundColor Green -$utilsplugindir = Join-Path -Path $rootdir -ChildPath "source\plugins\utils" -Write-Host("copying ruby util files from :" + $utilsplugindir + " to :" + $publishdir + " ...") -Copy-Item -Path $utilsplugindir -Destination $publishdir -Recurse -Force -Write-Host("successfully copied ruby util files from :" + $utilsplugindir + " to :" + $publishdir + " ") -ForegroundColor Green +# $utilsplugindir = Join-Path -Path $rootdir -ChildPath "source\plugins\utils" +# Write-Host("copying ruby util files from :" + $utilsplugindir + " to :" + $publishdir + " ...") +# Copy-Item -Path $utilsplugindir -Destination $publishdir -Recurse -Force +# Write-Host("successfully copied ruby util files from :" + $utilsplugindir + " to :" + $publishdir + " ") -ForegroundColor Green Set-Location $currentdir \ No newline at end of file diff --git a/source/plugins/go/src/extension/extension.go b/source/plugins/go/src/extension/extension.go index 5d27ece9c..4d78380bc 100644 --- a/source/plugins/go/src/extension/extension.go +++ b/source/plugins/go/src/extension/extension.go @@ -21,13 +21,13 @@ var extensionconfiglock sync.Mutex var logger *log.Logger var containerType string -func GetInstance(flbLogger *log.Logger, containerType string) *Extension { +func GetInstance(flbLogger *log.Logger, containertype string) *Extension { once.Do(func() { singleton = &Extension{make(map[string]string)} flbLogger.Println("Extension Instance created") }) logger = flbLogger - containerType = containerType + containerType = containertype return singleton } @@ -55,6 +55,7 @@ func getDataTypeToStreamIdMapping() (map[string]string, error) { taggedData := map[string]interface{}{"Request": "AgentTaggedData", "RequestId": guid.String(), "Tag": "ContainerInsights", "Version": "1"} jsonBytes, err := json.Marshal(taggedData) + // TODO: this error is unhandled var data []byte enc := codec.NewEncoderBytes(&data, new(codec.MsgpackHandle)) @@ -67,8 +68,8 @@ func getDataTypeToStreamIdMapping() (map[string]string, error) { if containerType != "" && strings.Compare(strings.ToLower(containerType), "prometheussidecar") == 0 { fs.sockAddress = fmt.Sprintf("/var/run/mdsd-%s/default_fluent.socket", containerType) } - responseBytes, err := FluentSocketWriter.WriteAndRead(fs, data) - defer FluentSocketWriter.disConnect(fs) + responseBytes, err := FluentSocketWriter.writeAndRead(fs, data) + defer FluentSocketWriter.disconnect(fs) logger.Printf("Info::mdsd::Making call to FluentSocket: %s to write and read the config data", fs.sockAddress) if err != nil { return datatypeOutputStreamMap, err diff --git a/source/plugins/go/src/extension/extension_test.go b/source/plugins/go/src/extension/extension_test.go index d52e63ed9..c3b5ef472 100644 --- a/source/plugins/go/src/extension/extension_test.go +++ b/source/plugins/go/src/extension/extension_test.go @@ -42,8 +42,8 @@ func Test_getDataTypeToStreamIdMapping(t *testing.T) { mock := NewMockIFluentSocketWriter(mockCtrl) sock := &FluentSocket{} sock.sockAddress = "/var/run/mdsd/default_fluent.socket" - mock.EXPECT().WriteAndRead(sock, gomock.Any()).Return([]byte(tt.mdsdResponse), nil).Times(1) - mock.EXPECT().disConnect(sock).Return(nil).Times(1) + mock.EXPECT().writeAndRead(sock, gomock.Any()).Return([]byte(tt.mdsdResponse), nil).Times(1) + mock.EXPECT().disconnect(sock).Return(nil).Times(1) // This is where calls to the normal socket writer calls are redirected to the mock. ActualFluentSocketWriter := FluentSocketWriter // save the old struct so that we can put it back later diff --git a/source/plugins/go/src/extension/socket_writer.go b/source/plugins/go/src/extension/socket_writer.go index 62a9b9fa0..bfd35f5e6 100644 --- a/source/plugins/go/src/extension/socket_writer.go +++ b/source/plugins/go/src/extension/socket_writer.go @@ -22,11 +22,11 @@ type FluentSocket struct { // begin mocking boilerplate type IFluentSocketWriter interface { connect(fluentSocket *FluentSocket) error - disConnect(fluentSocket *FluentSocket) error + disconnect(fluentSocket *FluentSocket) error writeWithRetries(fluentSocket *FluentSocket, data []byte) (int, error) read(fluentSocket *FluentSocket) ([]byte, error) - Write(fluentSocket *FluentSocket, payload []byte) (int, error) - WriteAndRead(fluentSocket *FluentSocket, payload []byte) ([]byte, error) + write(fluentSocket *FluentSocket, payload []byte) (int, error) + writeAndRead(fluentSocket *FluentSocket, payload []byte) ([]byte, error) } type FluentSocketWriterImpl struct{} @@ -51,7 +51,7 @@ func (FluentSocketWriterImpl) connect(fs *FluentSocket) error { return nil } -func (FluentSocketWriterImpl) disConnect(fs *FluentSocket) error { +func (FluentSocketWriterImpl) disconnect(fs *FluentSocket) error { if fs.socket != nil { fs.socket.Close() fs.socket = nil @@ -89,7 +89,7 @@ func (FluentSocketWriterImpl) read(fs *FluentSocket) ([]byte, error) { } -func (FluentSocketWriterImpl) Write(fs *FluentSocket, payload []byte) (int, error) { +func (FluentSocketWriterImpl) write(fs *FluentSocket, payload []byte) (int, error) { if fs.socket == nil { // previous write failed with permanent error and socket was closed. if err := FluentSocketWriter.connect(fs); err != nil { @@ -100,9 +100,9 @@ func (FluentSocketWriterImpl) Write(fs *FluentSocket, payload []byte) (int, erro return FluentSocketWriter.writeWithRetries(fs, payload) } -//WriteAndRead writes data to the socket and sends the response back -func (FluentSocketWriterImpl) WriteAndRead(fs *FluentSocket, payload []byte) ([]byte, error) { - _, err := FluentSocketWriter.Write(fs, payload) +//writeAndRead writes data to the socket and sends the response back +func (FluentSocketWriterImpl) writeAndRead(fs *FluentSocket, payload []byte) ([]byte, error) { + _, err := FluentSocketWriter.write(fs, payload) if err != nil { return nil, err } diff --git a/source/plugins/ruby/filter_cadvisor2mdm_test.rb b/source/plugins/ruby/filter_cadvisor2mdm_test.rb index 29c92730d..9d462fa84 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm_test.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm_test.rb @@ -1,8 +1,3 @@ -# TODO: can we get rid of this global flag -$in_unit_test = true - -# TODO: get rid of require test-unit if we switch to minitest -# require "test-unit" require 'minitest/autorun' # require 'fluent/test' diff --git a/source/plugins/ruby/in_kube_nodes_test.rb b/source/plugins/ruby/in_kube_nodes_test.rb index f84f5fd92..6638f36e8 100644 --- a/source/plugins/ruby/in_kube_nodes_test.rb +++ b/source/plugins/ruby/in_kube_nodes_test.rb @@ -1,6 +1,3 @@ -# TODO: can we get rid of this global flag -$in_unit_test = true - require 'minitest/autorun' require 'fluent/test' diff --git a/source/plugins/ruby/test_driver.rb b/source/plugins/ruby/test_driver.rb deleted file mode 100644 index aca4129a5..000000000 --- a/source/plugins/ruby/test_driver.rb +++ /dev/null @@ -1,6 +0,0 @@ -# TODO: can we get rid of this global flag -$in_unit_test = true - -Dir.glob("*_test.rb") do |filename| - require_relative filename -end diff --git a/source/plugins/ruby/test_registry.rb b/source/plugins/ruby/test_registry.rb deleted file mode 100644 index b27d4db35..000000000 --- a/source/plugins/ruby/test_registry.rb +++ /dev/null @@ -1,16 +0,0 @@ -# require_relative 'KubernetesApiClient' -require_relative 'ApplicationInsightsUtility' - - -class Test_registry - include Singleton - - attr_reader :applicationInsightsUtility, :env, :kubernetesApiClient - attr_writer :applicationInsightsUtility, :env, :kubernetesApiClient - - def initialize - @applicationInsightsUtility = ApplicationInsightsUtility - @env = ENV - @kubernetesApiClient = KubernetesApiClient - end -end From a7456e29d54457a75ee69db3eb983bb56e6b0c2f Mon Sep 17 00:00:00 2001 From: David Michelman Date: Wed, 18 Aug 2021 15:06:13 -0700 Subject: [PATCH 23/33] forgot to include test driver in last commit --- test/unit-tests/test_driver.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 test/unit-tests/test_driver.rb diff --git a/test/unit-tests/test_driver.rb b/test/unit-tests/test_driver.rb new file mode 100644 index 000000000..6cdb25de4 --- /dev/null +++ b/test/unit-tests/test_driver.rb @@ -0,0 +1,10 @@ +# TODO: can we get rid of this global flag? +$in_unit_test = true + +Dir.glob("../../source/plugins/ruby/*_test.rb") do |filename| + require_relative filename +end + +Dir.glob("../../build/linux/installer/scripts/*_test.rb") do |filename| + require_relative filename +end From 87689469b43be3bbf8af6fda165c1972f52c2601 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Wed, 18 Aug 2021 18:54:26 -0700 Subject: [PATCH 24/33] cleanup almost done, giving up on filter_cadvisor2mdm_test.rb for now --- .gitignore | 2 ++ source/plugins/ruby/KubernetesApiClient.rb | 6 ----- source/plugins/ruby/filter_cadvisor2mdm.rb | 11 +++----- .../plugins/ruby/filter_cadvisor2mdm_test.rb | 26 ++++++++++++------- source/plugins/ruby/in_kube_nodes.rb | 2 +- source/plugins/ruby/in_kube_nodes_test.rb | 4 +-- source/plugins/ruby/kubelet_utils.rb | 3 --- .../get_nodes_response_2.json | 1 + test/unit-tests/run_ruby_tests.sh | 10 ++++--- test/unit-tests/test_driver.rb | 8 ++++-- 10 files changed, 39 insertions(+), 34 deletions(-) create mode 100644 test/unit-tests/canned-api-responses/get_nodes_response_2.json diff --git a/.gitignore b/.gitignore index 9d678bbc3..fc1ada569 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ kubernetes/linux/Linux_ULINUX_1.0_x64_64_Release source/plugins/go/src/*.h *_mock.go *_log.txt +*.log +*.byebug_history \ No newline at end of file diff --git a/source/plugins/ruby/KubernetesApiClient.rb b/source/plugins/ruby/KubernetesApiClient.rb index dbc9f35f2..8925248d7 100644 --- a/source/plugins/ruby/KubernetesApiClient.rb +++ b/source/plugins/ruby/KubernetesApiClient.rb @@ -26,12 +26,6 @@ class KubernetesApiClient #@@IsLinuxCluster = nil @@KubeSystemNamespace = "kube-system" - # TODO: refactor this so that env can be passed in (For unit tests) - # options: - # 1. make it a singleton, first call to a function which uses the logger initializes it with the correct OS type - # 2. don't change anything. (do we care if unit tests can tell which OS they're running on?) - # 3. Keep some global state (like the object registry) - # this also needs to be changed in MdmMetricsGenerator.rb (and probably most other places which use the logger) @os_type = ENV["OS_TYPE"] if !@os_type.nil? && !@os_type.empty? && @os_type.strip.casecmp("windows") == 0 @LogPath = Constants::WINDOWS_LOG_PATH + "kubernetes_client_log.txt" diff --git a/source/plugins/ruby/filter_cadvisor2mdm.rb b/source/plugins/ruby/filter_cadvisor2mdm.rb index cc95fe2ce..9ab60d63d 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm.rb @@ -21,18 +21,12 @@ class CAdvisor2MdmFilter < Filter config_param :log_path, :string, :default => Constants::LINUX_LOG_PATH + "filter_cadvisor2mdm.log" config_param :metrics_to_collect, :string, :default => "Constants::CPU_USAGE_NANO_CORES,Constants::MEMORY_WORKING_SET_BYTES,Constants::MEMORY_RSS_BYTES,Constants::PV_USED_BYTES" - @@hostName = (OMS::Common.get_hostname) # TODO: mock this - @process_incoming_stream = true @metrics_to_collect_hash = {} @@metric_threshold_hash = {} @@controller_type = "" - def set_hostname (hostname) - @@hostname = hostname - end - def initialize super end @@ -47,13 +41,16 @@ def configure(conf) end end - def start(env=ENV, applicationInsightsUtility=ApplicationInsightsUtility, kubernetesApiClient=KubernetesApiClient, kubeletUtils=KubeletUtils) + def start(env=ENV, applicationInsightsUtility=ApplicationInsightsUtility, kubernetesApiClient=KubernetesApiClient, kubeletUtils=KubeletUtils, oms_common=OMS::Common) @env = env @AplicationInsightsUtility = applicationInsightsUtility @KubernetesAPIClient = kubernetesApiClient @KubeletUtils = kubeletUtils + @oms_common = oms_common super() + @@hostName = (@oms_common.get_hostname) + @@isWindows = false @@os_type = @env["OS_TYPE"] if !@@os_type.nil? && !@@os_type.empty? && @@os_type.strip.casecmp("windows") == 0 diff --git a/source/plugins/ruby/filter_cadvisor2mdm_test.rb b/source/plugins/ruby/filter_cadvisor2mdm_test.rb index 9d462fa84..2cc207200 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm_test.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm_test.rb @@ -1,5 +1,4 @@ require 'minitest/autorun' -# require 'fluent/test' require 'fluent/test/driver/filter' require 'fluent/test/helpers' @@ -8,6 +7,8 @@ require 'byebug' +# This is one way to stub a class. It's longer than the method demonstrated in in_kube_nodes_test.rb but gives more control +# over how the stub behaves class Ai_utility_stub class << self def sendCustomEvent(a, b) @@ -21,11 +22,11 @@ def sendExceptionTelemetry (errorstr) end class KubernetesApiClientMock < KubernetesApiClient - class GetNodesResponse - def body - return "{\"kind\":\"NodeList\",\"apiVersion\":\"v1\",\"metadata\":{\"selfLink\":\"/api/v1/nodes\",\"resourceVersion\":\"4597672\"},\"items\":[{\"metadata\":{\"name\":\"aks-nodepool1-24816391-vmss000000\",\"selfLink\":\"/api/v1/nodes/aks-nodepool1-24816391-vmss000000\",\"uid\":\"fe073f0a-e6bf-4d68-b4e5-ffaa42b91528\",\"resourceVersion\":\"4597521\",\"creationTimestamp\":\"2021-07-21T23:40:14Z\",\"labels\":{\"agentpool\":\"nodepool1\",\"beta.kubernetes.io/arch\":\"amd64\",\"beta.kubernetes.io/instance-type\":\"Standard_DS2_v2\",\"beta.kubernetes.io/os\":\"linux\",\"failure-domain.beta.kubernetes.io/region\":\"westus2\",\"failure-domain.beta.kubernetes.io/zone\":\"0\",\"kubernetes.azure.com/cluster\":\"MC_davidaks16_davidaks16_westus2\",\"kubernetes.azure.com/mode\":\"system\",\"kubernetes.azure.com/node-image-version\":\"AKSUbuntu-1804gen2containerd-2021.07.03\",\"kubernetes.azure.com/os-sku\":\"Ubuntu\",\"kubernetes.azure.com/role\":\"agent\",\"kubernetes.io/arch\":\"amd64\",\"kubernetes.io/hostname\":\"aks-nodepool1-24816391-vmss000000\",\"kubernetes.io/os\":\"linux\",\"kubernetes.io/role\":\"agent\",\"node-role.kubernetes.io/agent\":\"\",\"node.kubernetes.io/instance-type\":\"Standard_DS2_v2\",\"storageprofile\":\"managed\",\"storagetier\":\"Premium_LRS\",\"topology.kubernetes.io/region\":\"westus2\",\"topology.kubernetes.io/zone\":\"0\"},\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"0\",\"volumes.kubernetes.io/controller-managed-attach-detach\":\"true\"},\"managedFields\":[{\"manager\":\"kube-controller-manager\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-07-21T23:40:20Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:metadata\":{\"f:annotations\":{\"f:node.alpha.kubernetes.io/ttl\":{}}}}},{\"manager\":\"kubelet\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-07-21T23:40:24Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:metadata\":{\"f:annotations\":{\".\":{},\"f:volumes.kubernetes.io/controller-managed-attach-detach\":{}},\"f:labels\":{\".\":{},\"f:agentpool\":{},\"f:beta.kubernetes.io/arch\":{},\"f:beta.kubernetes.io/instance-type\":{},\"f:beta.kubernetes.io/os\":{},\"f:failure-domain.beta.kubernetes.io/region\":{},\"f:failure-domain.beta.kubernetes.io/zone\":{},\"f:kubernetes.azure.com/cluster\":{},\"f:kubernetes.azure.com/mode\":{},\"f:kubernetes.azure.com/node-image-version\":{},\"f:kubernetes.azure.com/os-sku\":{},\"f:kubernetes.azure.com/role\":{},\"f:kubernetes.io/arch\":{},\"f:kubernetes.io/hostname\":{},\"f:kubernetes.io/os\":{},\"f:node.kubernetes.io/instance-type\":{},\"f:storageprofile\":{},\"f:storagetier\":{},\"f:topology.kubernetes.io/region\":{},\"f:topology.kubernetes.io/zone\":{}}},\"f:spec\":{\"f:providerID\":{}},\"f:status\":{\"f:addresses\":{\".\":{},\"k:{\\\"type\\\":\\\"Hostname\\\"}\":{\".\":{},\"f:address\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"InternalIP\\\"}\":{\".\":{},\"f:address\":{},\"f:type\":{}}},\"f:allocatable\":{\".\":{},\"f:attachable-volumes-azure-disk\":{},\"f:cpu\":{},\"f:ephemeral-storage\":{},\"f:hugepages-1Gi\":{},\"f:hugepages-2Mi\":{},\"f:memory\":{},\"f:pods\":{}},\"f:capacity\":{\".\":{},\"f:attachable-volumes-azure-disk\":{},\"f:cpu\":{},\"f:ephemeral-storage\":{},\"f:hugepages-1Gi\":{},\"f:hugepages-2Mi\":{},\"f:memory\":{},\"f:pods\":{}},\"f:conditions\":{\".\":{},\"k:{\\\"type\\\":\\\"DiskPressure\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"MemoryPressure\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"PIDPressure\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"Ready\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}}},\"f:config\":{},\"f:daemonEndpoints\":{\"f:kubeletEndpoint\":{\"f:Port\":{}}},\"f:images\":{},\"f:nodeInfo\":{\"f:architecture\":{},\"f:bootID\":{},\"f:containerRuntimeVersion\":{},\"f:kernelVersion\":{},\"f:kubeProxyVersion\":{},\"f:kubeletVersion\":{},\"f:machineID\":{},\"f:operatingSystem\":{},\"f:osImage\":{},\"f:systemUUID\":{}}}}},{\"manager\":\"kubectl-label\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-07-21T23:40:53Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:metadata\":{\"f:labels\":{\"f:kubernetes.io/role\":{},\"f:node-role.kubernetes.io/agent\":{}}}}},{\"manager\":\"node-problem-detector\",\"operation\":\"Update\",\"apiVersion\":\"v1\",\"time\":\"2021-08-10T18:10:02Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:status\":{\"f:conditions\":{\"k:{\\\"type\\\":\\\"ContainerRuntimeProblem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FilesystemCorruptionProblem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FreezeScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentContainerdRestart\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentDockerRestart\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentKubeletRestart\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"FrequentUnregisterNetDevice\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"KernelDeadlock\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"KubeletProblem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"PreemptScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"ReadonlyFilesystem\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"RebootScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"RedeployScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}},\"k:{\\\"type\\\":\\\"TerminateScheduled\\\"}\":{\".\":{},\"f:lastHeartbeatTime\":{},\"f:lastTransitionTime\":{},\"f:message\":{},\"f:reason\":{},\"f:status\":{},\"f:type\":{}}}}}}]},\"spec\":{\"providerID\":\"azure:///subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/mc_davidaks16_davidaks16_westus2/providers/Microsoft.Compute/virtualMachineScaleSets/aks-nodepool1-24816391-vmss/virtualMachines/0\"},\"status\":{\"capacity\":{\"attachable-volumes-azure-disk\":\"8\",\"cpu\":\"2\",\"ephemeral-storage\":\"129900528Ki\",\"hugepages-1Gi\":\"0\",\"hugepages-2Mi\":\"0\",\"memory\":\"7120616Ki\",\"pods\":\"30\"},\"allocatable\":{\"attachable-volumes-azure-disk\":\"8\",\"cpu\":\"1900m\",\"ephemeral-storage\":\"119716326407\",\"hugepages-1Gi\":\"0\",\"hugepages-2Mi\":\"0\",\"memory\":\"4675304Ki\",\"pods\":\"30\"},\"conditions\":[{\"type\":\"FrequentContainerdRestart\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentContainerdRestart\",\"message\":\"containerd is functioning properly\"},{\"type\":\"FreezeScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFreezeScheduled\",\"message\":\"VM has no scheduled Freeze event\"},{\"type\":\"FrequentDockerRestart\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentDockerRestart\",\"message\":\"docker is functioning properly\"},{\"type\":\"FilesystemCorruptionProblem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"FilesystemIsOK\",\"message\":\"Filesystem is healthy\"},{\"type\":\"KernelDeadlock\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"KernelHasNoDeadlock\",\"message\":\"kernel has no deadlock\"},{\"type\":\"TerminateScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoTerminateScheduled\",\"message\":\"VM has no scheduled Terminate event\"},{\"type\":\"ReadonlyFilesystem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"FilesystemIsNotReadOnly\",\"message\":\"Filesystem is not read-only\"},{\"type\":\"FrequentUnregisterNetDevice\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentUnregisterNetDevice\",\"message\":\"node is functioning properly\"},{\"type\":\"KubeletProblem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"KubeletIsUp\",\"message\":\"kubelet service is up\"},{\"type\":\"PreemptScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:11:11Z\",\"reason\":\"NoPreemptScheduled\",\"message\":\"VM has no scheduled Preempt event\"},{\"type\":\"RedeployScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoRedeployScheduled\",\"message\":\"VM has no scheduled Redeploy event\"},{\"type\":\"ContainerRuntimeProblem\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"ContainerRuntimeIsUp\",\"message\":\"container runtime service is up\"},{\"type\":\"FrequentKubeletRestart\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoFrequentKubeletRestart\",\"message\":\"kubelet is functioning properly\"},{\"type\":\"RebootScheduled\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:57:20Z\",\"lastTransitionTime\":\"2021-08-10T18:10:01Z\",\"reason\":\"NoRebootScheduled\",\"message\":\"VM has no scheduled Reboot event\"},{\"type\":\"MemoryPressure\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:14Z\",\"reason\":\"KubeletHasSufficientMemory\",\"message\":\"kubelet has sufficient memory available\"},{\"type\":\"DiskPressure\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:14Z\",\"reason\":\"KubeletHasNoDiskPressure\",\"message\":\"kubelet has no disk pressure\"},{\"type\":\"PIDPressure\",\"status\":\"False\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:14Z\",\"reason\":\"KubeletHasSufficientPID\",\"message\":\"kubelet has sufficient PID available\"},{\"type\":\"Ready\",\"status\":\"True\",\"lastHeartbeatTime\":\"2021-08-11T02:58:37Z\",\"lastTransitionTime\":\"2021-07-21T23:40:24Z\",\"reason\":\"KubeletReady\",\"message\":\"kubelet is posting ready status. AppArmor enabled\"}],\"addresses\":[{\"type\":\"Hostname\",\"address\":\"aks-nodepool1-24816391-vmss000000\"},{\"type\":\"InternalIP\",\"address\":\"10.240.0.4\"}],\"daemonEndpoints\":{\"kubeletEndpoint\":{\"Port\":10250}},\"nodeInfo\":{\"machineID\":\"17a654260e2c4a9bb3a3eb4b4188e4b4\",\"systemUUID\":\"7ff599e4-909e-4950-a044-ff8613af3af9\",\"bootID\":\"02bb865b-a469-43cd-8b0b-5ceb4ecd80b0\",\"kernelVersion\":\"5.4.0-1051-azure\",\"osImage\":\"Ubuntu 18.04.5 LTS\",\"containerRuntimeVersion\":\"containerd://1.4.4+azure\",\"kubeletVersion\":\"v1.19.11\",\"kubeProxyVersion\":\"v1.19.11\",\"operatingSystem\":\"linux\",\"architecture\":\"amd64\"},\"images\":[{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021-1\"],\"sizeBytes\":331689060},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021\"],\"sizeBytes\":330099815},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021-hotfix\"],\"sizeBytes\":271471426},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021\"],\"sizeBytes\":269703297},{\"names\":[\"mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod03262021\"],\"sizeBytes\":264732875},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.19.0\"],\"sizeBytes\":166352383},{\"names\":[\"mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210623.2\"],\"sizeBytes\":147750148},{\"names\":[\"mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210524.1\"],\"sizeBytes\":146446618},{\"names\":[\"mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210427.1\"],\"sizeBytes\":136242776},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.8.9.5\"],\"sizeBytes\":101794833},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.47.0\"],\"sizeBytes\":101445696},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/autoscaler/cluster-proportional-autoscaler:1.3.0_v0.0.5\"],\"sizeBytes\":101194562},{\"names\":[\"mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210623.2\"],\"sizeBytes\":96125176},{\"names\":[\"mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210524.1\"],\"sizeBytes\":95879501},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/exechealthz:1.2_v0.0.5\"],\"sizeBytes\":94348102},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.8.9.2\"],\"sizeBytes\":93537927},{\"names\":[\"mcr.microsoft.com/aks/acc/sgx-attestation:2.0\"],\"sizeBytes\":91841669},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.4.0\"],\"sizeBytes\":91324193},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.2.0\"],\"sizeBytes\":89103171},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.0.1-rc3\"],\"sizeBytes\":86839805},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.2.0\"],\"sizeBytes\":86488586},{\"names\":[\"mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210427.1\"],\"sizeBytes\":86120048},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.3.0\"],\"sizeBytes\":81252495},{\"names\":[\"mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.4.0\"],\"sizeBytes\":79586703},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.4.0\"],\"sizeBytes\":78795016},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.2.0\"],\"sizeBytes\":76527179},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.1.8\"],\"sizeBytes\":75025803},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.2.2_hotfix\"],\"sizeBytes\":73533889},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.3.1\"],\"sizeBytes\":72242894},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.2.8\"],\"sizeBytes\":70622822},{\"names\":[\"mcr.microsoft.com/oss/nvidia/k8s-device-plugin:v0.9.0\"],\"sizeBytes\":67291599},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.1\"],\"sizeBytes\":66415836},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc7\"],\"sizeBytes\":65965658},{\"names\":[\"mcr.microsoft.com/containernetworking/azure-npm:v1.2.1\"],\"sizeBytes\":64123775},{\"names\":[\"mcr.microsoft.com/oss/calico/cni:v3.8.9.3\"],\"sizeBytes\":63581323},{\"names\":[\"mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8\"],\"sizeBytes\":63154716},{\"names\":[\"mcr.microsoft.com/oss/calico/cni:v3.8.9.2\"],\"sizeBytes\":61626312},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.18.1\"],\"sizeBytes\":60500885},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.17.2\"],\"sizeBytes\":58419768},{\"names\":[\"mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8_hotfix\",\"mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8post2\"],\"sizeBytes\":56368756},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:282543237a1aa3f407656290f454b7068a92e1abe2156082c750d5abfbcad90c\",\"mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.2\"],\"sizeBytes\":56310724},{\"names\":[\"mcr.microsoft.com/oss/calico/node:v3.19.0\"],\"sizeBytes\":55228749},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.1\"],\"sizeBytes\":54692048},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc3\"],\"sizeBytes\":50803639},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.19\"],\"sizeBytes\":49759361},{\"names\":[\"mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.5\"],\"sizeBytes\":49704644},{\"names\":[\"mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.21\"],\"sizeBytes\":49372390},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:a64d3538b72905b07356881314755b02db3675ff47ee2bcc49dd7be856e285d5\",\"mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526\"],\"sizeBytes\":49322942},{\"names\":[\"mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.4\"],\"sizeBytes\":48108311},{\"names\":[\"mcr.microsoft.com/oss/kubernetes/kubernetes-dashboard:v1.10.1\"],\"sizeBytes\":44907744}],\"config\":{}}}]}\n" - end - end + class GetNodesResponse + def body + return File.open("test/unit-tests/canned-api-responses/get_nodes_response_2.json").read + end + end class << self def getKubeResourceInfo(resource, api_group: nil) if resource == "nodes?fieldSelector=metadata.name%3DWIN-T14B9CT7KMS" @@ -82,24 +83,29 @@ def test_filter applicationInsightsUtility = Ai_utility_stub.new() kubernetesApiClient = KubernetesApiClientMock + oms_common = Minitest::Mock.new + oms_common.expect(:get_hostname, "aks-nodepool1-24816391-vmss000000") + config = %[ metrics_to_collect cpuUsageNanoCores,memoryWorkingSetBytes,pvUsedBytes @log_level info ] data = [ - {"tag" => "mdm.cadvisorperf", "time" => 1628198199.2757478, "data" => {"DataItems"=>[{"Timestamp"=>"2021-08-05T21:16:39Z", "Host"=>"akswin00000c", "ObjectName"=>"K8SContainer", "InstanceName"=>"/subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/davidwin6/providers/Microsoft.ContainerService/managedClusters/davidwin6/9bb73e59-9034-474a-92ab-5e028f18dbe9/omsagent-win", "Collections"=>[{"CounterName"=>"memoryWorkingSetBytes", "Value"=>272093184}]}], "DataType"=>"LINUX_PERF_BLOB", "IPName"=>"LogManagement"}} + {"tag" => "mdm.cadvisorperf", "time" => 1629337471, "data" => {"Timestamp"=>"2021-08-19T01:44:31Z", "Host"=>"aks-nodepool1-24031368-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"/subscriptions/9b96ebbd-c57a-42d1-bbe9-b69296e4c7fb/resourceGroups/davidbuild1/providers/Microsoft.ContainerService/managedClusters/davidbuild1/aks-nodepool1-24031368-vmss000000", "json_Collections"=>"[{\"CounterName\":\"memoryRssBytes\",\"Value\":511778816}]"}} ] expected_output = [ - {"tag" => "mdm.cadvisorperf", "time" => 1628198199.2757478, "data" => {"DataItems"=>[{"Timestamp"=>"2021-08-05T21:16:39Z", "Host"=>"akswin00000c", "ObjectName"=>"K8SContainer", "InstanceName"=>"/subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/davidwin6/providers/Microsoft.ContainerService/managedClusters/davidwin6/9bb73e59-9034-474a-92ab-5e028f18dbe9/omsagent-win", "Collections"=>[{"CounterName"=>"memoryWorkingSetBytes", "Value"=>272093184}]}], "DataType"=>"LINUX_PERF_BLOB", "IPName"=>"LogManagement"}} + {"time"=>"2021-08-19T01:44:31Z", "data"=>{"baseData"=>{"metric"=>"memoryRssBytes", "namespace"=>"Insights.Container/nodes", "dimNames"=>["host"], "series"=>[{"dimValues"=>["aks-nodepool1-24031368-vmss000000"], "min"=>511778816, "max"=>511778816, "sum"=>511778816, "count"=>1}]}}}, + {"time"=>"2021-08-19T01:44:31Z", "data"=>{"baseData"=>{"metric"=>"memoryRssPercentage", "namespace"=>"Insights.Container/nodes", "dimNames"=>["host"], "series"=>[{"dimValues"=>["aks-nodepool1-24031368-vmss000000"], "min"=>7.018830955074673, "max"=>7.018830955074673, "sum"=>7.018830955074673, "count"=>1}]}}} ] d = create_driver(config) - d.instance.set_hostname("aks-nodepool1-24816391-vmss000000") - d.instance.start(env=env, applicationInsightsUtility=applicationInsightsUtility, kubernetesApiClient=kubernetesApiClient) # TODO: why doesn't the fluentd test harness do this automatically? + # TODO: why doesn't the fluentd test harness call start automatically? + d.instance.start(env=env, applicationInsightsUtility=applicationInsightsUtility, kubernetesApiClient=kubernetesApiClient, oms_common=oms_common) time = event_time + # byebug d.run do d.feed(data[0]["tag"], time, data[0]["data"]) end diff --git a/source/plugins/ruby/in_kube_nodes.rb b/source/plugins/ruby/in_kube_nodes.rb index f69d84585..38021f4e4 100644 --- a/source/plugins/ruby/in_kube_nodes.rb +++ b/source/plugins/ruby/in_kube_nodes.rb @@ -17,7 +17,7 @@ def initialize (kubernetesApiClient=nil, applicationInsightsUtility=nil, extensi require_relative "KubernetesApiClient" require_relative "ApplicationInsightsUtility" - # TODO: oms_common and omslog appear to be unused. + # TODO: oms_common and omslog appear to be unused. Remove them if they are # require_relative "oms_common" # require_relative "omslog" require_relative "extension_utils" diff --git a/source/plugins/ruby/in_kube_nodes_test.rb b/source/plugins/ruby/in_kube_nodes_test.rb index 6638f36e8..f148c8009 100644 --- a/source/plugins/ruby/in_kube_nodes_test.rb +++ b/source/plugins/ruby/in_kube_nodes_test.rb @@ -48,7 +48,7 @@ def extensionUtils.isAADMSIAuthMode false end - nodes_api_response = eval(File.open("../../../test/unit-tests/canned-api-responses/kube-nodes.txt").read) + nodes_api_response = eval(File.open("test/unit-tests/canned-api-responses/kube-nodes.txt").read) kubeApiClient.expect(:getResourcesAndContinuationToken, [nil, nodes_api_response], ["nodes?limit=200"]) kubeApiClient.expect(:getClusterName, "/cluster-name") kubeApiClient.expect(:getClusterId, "/cluster-id") @@ -110,7 +110,7 @@ def extensionUtils.isAADMSIAuthMode # state other than their arguments), so there is no need to mock them (this test file would be far longer and # more brittle). Instead, in_kube_nodes bypasses the mock and directly calls these functions in KubernetesApiClient. # Ideally the pure functions in KubernetesApiClient would be refactored into their own file. - nodes_api_response = eval(File.open("../../../test/unit-tests/canned-api-responses/kube-nodes-malformed.txt").read) + nodes_api_response = eval(File.open("test/unit-tests/canned-api-responses/kube-nodes-malformed.txt").read) kubeApiClient.expect(:getResourcesAndContinuationToken, [nil, nodes_api_response], ["nodes?limit=200"]) kubeApiClient.expect(:getClusterName, "/cluster-name") kubeApiClient.expect(:getClusterName, "/cluster-name") diff --git a/source/plugins/ruby/kubelet_utils.rb b/source/plugins/ruby/kubelet_utils.rb index f5ee1e57c..fca67eb5e 100644 --- a/source/plugins/ruby/kubelet_utils.rb +++ b/source/plugins/ruby/kubelet_utils.rb @@ -214,9 +214,6 @@ def get_all_container_limits @log.info "Error in get_all_container_limits: #{errorStr}" ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) end - @log.info "containerCpuLimitHash: #{containerCpuLimitHash}" - @log.info "containerMemoryLimitHash: #{containerMemoryLimitHash}" - @log.info "containerResourceDimensionHash: #{containerResourceDimensionHash}" return [containerCpuLimitHash, containerMemoryLimitHash, containerResourceDimensionHash] end diff --git a/test/unit-tests/canned-api-responses/get_nodes_response_2.json b/test/unit-tests/canned-api-responses/get_nodes_response_2.json new file mode 100644 index 000000000..1cc5ec151 --- /dev/null +++ b/test/unit-tests/canned-api-responses/get_nodes_response_2.json @@ -0,0 +1 @@ +{"kind":"NodeList","apiVersion":"v1","metadata":{"selfLink":"/api/v1/nodes","resourceVersion":"4597672"},"items":[{"metadata":{"name":"aks-nodepool1-24816391-vmss000000","selfLink":"/api/v1/nodes/aks-nodepool1-24816391-vmss000000","uid":"fe073f0a-e6bf-4d68-b4e5-ffaa42b91528","resourceVersion":"4597521","creationTimestamp":"2021-07-21T23:40:14Z","labels":{"agentpool":"nodepool1","beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/instance-type":"Standard_DS2_v2","beta.kubernetes.io/os":"linux","failure-domain.beta.kubernetes.io/region":"westus2","failure-domain.beta.kubernetes.io/zone":"0","kubernetes.azure.com/cluster":"MC_davidaks16_davidaks16_westus2","kubernetes.azure.com/mode":"system","kubernetes.azure.com/node-image-version":"AKSUbuntu-1804gen2containerd-2021.07.03","kubernetes.azure.com/os-sku":"Ubuntu","kubernetes.azure.com/role":"agent","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"aks-nodepool1-24816391-vmss000000","kubernetes.io/os":"linux","kubernetes.io/role":"agent","node-role.kubernetes.io/agent":"","node.kubernetes.io/instance-type":"Standard_DS2_v2","storageprofile":"managed","storagetier":"Premium_LRS","topology.kubernetes.io/region":"westus2","topology.kubernetes.io/zone":"0"},"annotations":{"node.alpha.kubernetes.io/ttl":"0","volumes.kubernetes.io/controller-managed-attach-detach":"true"},"managedFields":[{"manager":"kube-controller-manager","operation":"Update","apiVersion":"v1","time":"2021-07-21T23:40:20Z","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{"f:node.alpha.kubernetes.io/ttl":{}}}}},{"manager":"kubelet","operation":"Update","apiVersion":"v1","time":"2021-07-21T23:40:24Z","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:volumes.kubernetes.io/controller-managed-attach-detach":{}},"f:labels":{".":{},"f:agentpool":{},"f:beta.kubernetes.io/arch":{},"f:beta.kubernetes.io/instance-type":{},"f:beta.kubernetes.io/os":{},"f:failure-domain.beta.kubernetes.io/region":{},"f:failure-domain.beta.kubernetes.io/zone":{},"f:kubernetes.azure.com/cluster":{},"f:kubernetes.azure.com/mode":{},"f:kubernetes.azure.com/node-image-version":{},"f:kubernetes.azure.com/os-sku":{},"f:kubernetes.azure.com/role":{},"f:kubernetes.io/arch":{},"f:kubernetes.io/hostname":{},"f:kubernetes.io/os":{},"f:node.kubernetes.io/instance-type":{},"f:storageprofile":{},"f:storagetier":{},"f:topology.kubernetes.io/region":{},"f:topology.kubernetes.io/zone":{}}},"f:spec":{"f:providerID":{}},"f:status":{"f:addresses":{".":{},"k:{\"type\":\"Hostname\"}":{".":{},"f:address":{},"f:type":{}},"k:{\"type\":\"InternalIP\"}":{".":{},"f:address":{},"f:type":{}}},"f:allocatable":{".":{},"f:attachable-volumes-azure-disk":{},"f:cpu":{},"f:ephemeral-storage":{},"f:hugepages-1Gi":{},"f:hugepages-2Mi":{},"f:memory":{},"f:pods":{}},"f:capacity":{".":{},"f:attachable-volumes-azure-disk":{},"f:cpu":{},"f:ephemeral-storage":{},"f:hugepages-1Gi":{},"f:hugepages-2Mi":{},"f:memory":{},"f:pods":{}},"f:conditions":{".":{},"k:{\"type\":\"DiskPressure\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"MemoryPressure\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"PIDPressure\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Ready\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}},"f:config":{},"f:daemonEndpoints":{"f:kubeletEndpoint":{"f:Port":{}}},"f:images":{},"f:nodeInfo":{"f:architecture":{},"f:bootID":{},"f:containerRuntimeVersion":{},"f:kernelVersion":{},"f:kubeProxyVersion":{},"f:kubeletVersion":{},"f:machineID":{},"f:operatingSystem":{},"f:osImage":{},"f:systemUUID":{}}}}},{"manager":"kubectl-label","operation":"Update","apiVersion":"v1","time":"2021-07-21T23:40:53Z","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:labels":{"f:kubernetes.io/role":{},"f:node-role.kubernetes.io/agent":{}}}}},{"manager":"node-problem-detector","operation":"Update","apiVersion":"v1","time":"2021-08-10T18:10:02Z","fieldsType":"FieldsV1","fieldsV1":{"f:status":{"f:conditions":{"k:{\"type\":\"ContainerRuntimeProblem\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FilesystemCorruptionProblem\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FreezeScheduled\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FrequentContainerdRestart\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FrequentDockerRestart\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FrequentKubeletRestart\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FrequentUnregisterNetDevice\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"KernelDeadlock\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"KubeletProblem\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"PreemptScheduled\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"ReadonlyFilesystem\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"RebootScheduled\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"RedeployScheduled\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"TerminateScheduled\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}}}}}]},"spec":{"providerID":"azure:///subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/mc_davidaks16_davidaks16_westus2/providers/Microsoft.Compute/virtualMachineScaleSets/aks-nodepool1-24816391-vmss/virtualMachines/0"},"status":{"capacity":{"attachable-volumes-azure-disk":"8","cpu":"2","ephemeral-storage":"129900528Ki","hugepages-1Gi":"0","hugepages-2Mi":"0","memory":"7120616Ki","pods":"30"},"allocatable":{"attachable-volumes-azure-disk":"8","cpu":"1900m","ephemeral-storage":"119716326407","hugepages-1Gi":"0","hugepages-2Mi":"0","memory":"4675304Ki","pods":"30"},"conditions":[{"type":"FrequentContainerdRestart","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoFrequentContainerdRestart","message":"containerd is functioning properly"},{"type":"FreezeScheduled","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoFreezeScheduled","message":"VM has no scheduled Freeze event"},{"type":"FrequentDockerRestart","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoFrequentDockerRestart","message":"docker is functioning properly"},{"type":"FilesystemCorruptionProblem","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"FilesystemIsOK","message":"Filesystem is healthy"},{"type":"KernelDeadlock","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"KernelHasNoDeadlock","message":"kernel has no deadlock"},{"type":"TerminateScheduled","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoTerminateScheduled","message":"VM has no scheduled Terminate event"},{"type":"ReadonlyFilesystem","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"FilesystemIsNotReadOnly","message":"Filesystem is not read-only"},{"type":"FrequentUnregisterNetDevice","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoFrequentUnregisterNetDevice","message":"node is functioning properly"},{"type":"KubeletProblem","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"KubeletIsUp","message":"kubelet service is up"},{"type":"PreemptScheduled","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:11:11Z","reason":"NoPreemptScheduled","message":"VM has no scheduled Preempt event"},{"type":"RedeployScheduled","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoRedeployScheduled","message":"VM has no scheduled Redeploy event"},{"type":"ContainerRuntimeProblem","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"ContainerRuntimeIsUp","message":"container runtime service is up"},{"type":"FrequentKubeletRestart","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoFrequentKubeletRestart","message":"kubelet is functioning properly"},{"type":"RebootScheduled","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoRebootScheduled","message":"VM has no scheduled Reboot event"},{"type":"MemoryPressure","status":"False","lastHeartbeatTime":"2021-08-11T02:58:37Z","lastTransitionTime":"2021-07-21T23:40:14Z","reason":"KubeletHasSufficientMemory","message":"kubelet has sufficient memory available"},{"type":"DiskPressure","status":"False","lastHeartbeatTime":"2021-08-11T02:58:37Z","lastTransitionTime":"2021-07-21T23:40:14Z","reason":"KubeletHasNoDiskPressure","message":"kubelet has no disk pressure"},{"type":"PIDPressure","status":"False","lastHeartbeatTime":"2021-08-11T02:58:37Z","lastTransitionTime":"2021-07-21T23:40:14Z","reason":"KubeletHasSufficientPID","message":"kubelet has sufficient PID available"},{"type":"Ready","status":"True","lastHeartbeatTime":"2021-08-11T02:58:37Z","lastTransitionTime":"2021-07-21T23:40:24Z","reason":"KubeletReady","message":"kubelet is posting ready status. AppArmor enabled"}],"addresses":[{"type":"Hostname","address":"aks-nodepool1-24816391-vmss000000"},{"type":"InternalIP","address":"10.240.0.4"}],"daemonEndpoints":{"kubeletEndpoint":{"Port":10250}},"nodeInfo":{"machineID":"17a654260e2c4a9bb3a3eb4b4188e4b4","systemUUID":"7ff599e4-909e-4950-a044-ff8613af3af9","bootID":"02bb865b-a469-43cd-8b0b-5ceb4ecd80b0","kernelVersion":"5.4.0-1051-azure","osImage":"Ubuntu 18.04.5 LTS","containerRuntimeVersion":"containerd://1.4.4+azure","kubeletVersion":"v1.19.11","kubeProxyVersion":"v1.19.11","operatingSystem":"linux","architecture":"amd64"},"images":[{"names":["mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021-1"],"sizeBytes":331689060},{"names":["mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021"],"sizeBytes":330099815},{"names":["mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021-hotfix"],"sizeBytes":271471426},{"names":["mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021"],"sizeBytes":269703297},{"names":["mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod03262021"],"sizeBytes":264732875},{"names":["mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.19.0"],"sizeBytes":166352383},{"names":["mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210623.2"],"sizeBytes":147750148},{"names":["mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210524.1"],"sizeBytes":146446618},{"names":["mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210427.1"],"sizeBytes":136242776},{"names":["mcr.microsoft.com/oss/calico/node:v3.8.9.5"],"sizeBytes":101794833},{"names":["mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.47.0"],"sizeBytes":101445696},{"names":["mcr.microsoft.com/oss/kubernetes/autoscaler/cluster-proportional-autoscaler:1.3.0_v0.0.5"],"sizeBytes":101194562},{"names":["mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210623.2"],"sizeBytes":96125176},{"names":["mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210524.1"],"sizeBytes":95879501},{"names":["mcr.microsoft.com/oss/kubernetes/exechealthz:1.2_v0.0.5"],"sizeBytes":94348102},{"names":["mcr.microsoft.com/oss/calico/node:v3.8.9.2"],"sizeBytes":93537927},{"names":["mcr.microsoft.com/aks/acc/sgx-attestation:2.0"],"sizeBytes":91841669},{"names":["mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.4.0"],"sizeBytes":91324193},{"names":["mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.2.0"],"sizeBytes":89103171},{"names":["mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.0.1-rc3"],"sizeBytes":86839805},{"names":["mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.2.0"],"sizeBytes":86488586},{"names":["mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210427.1"],"sizeBytes":86120048},{"names":["mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.3.0"],"sizeBytes":81252495},{"names":["mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.4.0"],"sizeBytes":79586703},{"names":["mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.4.0"],"sizeBytes":78795016},{"names":["mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.2.0"],"sizeBytes":76527179},{"names":["mcr.microsoft.com/containernetworking/azure-npm:v1.1.8"],"sizeBytes":75025803},{"names":["mcr.microsoft.com/containernetworking/azure-npm:v1.2.2_hotfix"],"sizeBytes":73533889},{"names":["mcr.microsoft.com/containernetworking/azure-npm:v1.3.1"],"sizeBytes":72242894},{"names":["mcr.microsoft.com/containernetworking/azure-npm:v1.2.8"],"sizeBytes":70622822},{"names":["mcr.microsoft.com/oss/nvidia/k8s-device-plugin:v0.9.0"],"sizeBytes":67291599},{"names":["mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.1"],"sizeBytes":66415836},{"names":["mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc7"],"sizeBytes":65965658},{"names":["mcr.microsoft.com/containernetworking/azure-npm:v1.2.1"],"sizeBytes":64123775},{"names":["mcr.microsoft.com/oss/calico/cni:v3.8.9.3"],"sizeBytes":63581323},{"names":["mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8"],"sizeBytes":63154716},{"names":["mcr.microsoft.com/oss/calico/cni:v3.8.9.2"],"sizeBytes":61626312},{"names":["mcr.microsoft.com/oss/calico/node:v3.18.1"],"sizeBytes":60500885},{"names":["mcr.microsoft.com/oss/calico/node:v3.17.2"],"sizeBytes":58419768},{"names":["mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8_hotfix","mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8post2"],"sizeBytes":56368756},{"names":["mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:282543237a1aa3f407656290f454b7068a92e1abe2156082c750d5abfbcad90c","mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.2"],"sizeBytes":56310724},{"names":["mcr.microsoft.com/oss/calico/node:v3.19.0"],"sizeBytes":55228749},{"names":["mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.1"],"sizeBytes":54692048},{"names":["mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc3"],"sizeBytes":50803639},{"names":["mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.19"],"sizeBytes":49759361},{"names":["mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.5"],"sizeBytes":49704644},{"names":["mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.21"],"sizeBytes":49372390},{"names":["mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:a64d3538b72905b07356881314755b02db3675ff47ee2bcc49dd7be856e285d5","mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526"],"sizeBytes":49322942},{"names":["mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.4"],"sizeBytes":48108311},{"names":["mcr.microsoft.com/oss/kubernetes/kubernetes-dashboard:v1.10.1"],"sizeBytes":44907744}],"config":{}}}]} \ No newline at end of file diff --git a/test/unit-tests/run_ruby_tests.sh b/test/unit-tests/run_ruby_tests.sh index 7d1f4bc03..103704d4a 100755 --- a/test/unit-tests/run_ruby_tests.sh +++ b/test/unit-tests/run_ruby_tests.sh @@ -1,8 +1,12 @@ -#TODO: add support for running a single specific test +# this script will exit with an error if any commands exit with an error +set -e + +# NOTE: to run a specific test (instead of all) use the following arguments: --name test_name +# ex: run_ruby_tests.sh --name test_basic_single_node OLD_PATH=$(pwd) SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" -cd $SCRIPTPATH/../../source/plugins/ruby -ruby test_driver.rb +# cd $SCRIPTPATH/../../source/plugins/ruby +ruby $SCRIPTPATH/test_driver.rb $1 $2 cd $OLD_PATH diff --git a/test/unit-tests/test_driver.rb b/test/unit-tests/test_driver.rb index 6cdb25de4..f4593748d 100644 --- a/test/unit-tests/test_driver.rb +++ b/test/unit-tests/test_driver.rb @@ -1,10 +1,14 @@ # TODO: can we get rid of this global flag? $in_unit_test = true -Dir.glob("../../source/plugins/ruby/*_test.rb") do |filename| +script_path = __dir__ +# go to the base directory of the repository +Dir.chdir(File.join(__dir__, "../..")) + +Dir.glob(File.join(script_path, "../../source/plugins/ruby/*_test.rb")) do |filename| require_relative filename end -Dir.glob("../../build/linux/installer/scripts/*_test.rb") do |filename| +Dir.glob(File.join(script_path, "../../build/linux/installer/scripts/*_test.rb")) do |filename| require_relative filename end From ad637d3d81350848b5824455f61a203cb8e84abe Mon Sep 17 00:00:00 2001 From: David Michelman Date: Mon, 23 Aug 2021 12:12:38 -0700 Subject: [PATCH 25/33] about to try to remove ^M newlines --- Dev Guide.md | 2 +- source/plugins/ruby/filter_cadvisor2mdm.rb | 137 +++++----- .../plugins/ruby/filter_cadvisor2mdm_test.rb | 234 +++++++++--------- source/plugins/ruby/kubelet_utils.rb | 3 + 4 files changed, 185 insertions(+), 191 deletions(-) diff --git a/Dev Guide.md b/Dev Guide.md index 18596f2b6..51a23959e 100644 --- a/Dev Guide.md +++ b/Dev Guide.md @@ -13,7 +13,7 @@ To run all unit tests run the commands `test/unit-tests/run_go_tests.sh` and `te 1. Unit tests should go in their own file, but in the same folder as the source code their testing. For example, the tests for `in_kube_nodes.rb` are in `in_kube_nodes_test.rb`. Both files are in the folder `source/plugin/ruby`. ### Ruby -Sample tests are provided in [in_kube_nodes_test.rb](source/plugin/ruby/in_kube_nodes_test.rb) and [filter_cadvisor2mdm_test.rb](source/plugin/ruby/filter_cadvisor2mdm_test.rb). They are meant to demo the tooling used for unit tests (as opposed to being comprehensive tests). Basic techniques like mocking are demonstrated there. +Sample tests are provided in [in_kube_nodes_test.rb](source/plugin/ruby/in_kube_nodes_test.rb). They are meant to demo the tooling used for unit tests (as opposed to being comprehensive tests). Basic techniques like mocking are demonstrated there. #### Conventions: 1. When modifying a fluentd plugin for unit testing, any mocked classes (like KubernetesApiClient, applicationInsightsUtility, env, etc.) should be passed in as optional arguments of initialize. For example: diff --git a/source/plugins/ruby/filter_cadvisor2mdm.rb b/source/plugins/ruby/filter_cadvisor2mdm.rb index 9ab60d63d..6bafa372a 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm.rb @@ -12,55 +12,48 @@ module Fluent::Plugin require_relative "kubelet_utils" require_relative "MdmMetricsGenerator" require_relative "in_kube_nodes" - require_relative "constants" class CAdvisor2MdmFilter < Filter Fluent::Plugin.register_filter("cadvisor2mdm", self) config_param :enable_log, :integer, :default => 0 - config_param :log_path, :string, :default => Constants::LINUX_LOG_PATH + "filter_cadvisor2mdm.log" + config_param :log_path, :string, :default => "/var/opt/microsoft/docker-cimprov/log/filter_cadvisor2mdm.log" config_param :metrics_to_collect, :string, :default => "Constants::CPU_USAGE_NANO_CORES,Constants::MEMORY_WORKING_SET_BYTES,Constants::MEMORY_RSS_BYTES,Constants::PV_USED_BYTES" + @@hostName = (OMS::Common.get_hostname) + @process_incoming_stream = true @metrics_to_collect_hash = {} @@metric_threshold_hash = {} @@controller_type = "" + @@isWindows = false + @@os_type = ENV["OS_TYPE"] + if !@@os_type.nil? && !@@os_type.empty? && @@os_type.strip.casecmp("windows") == 0 + @@isWindows = true + end + def initialize super end def configure(conf) super - @Log = nil + @log = nil if @enable_log - @Log = Logger.new(@log_path, 1, 5000000) - @Log.debug { "Starting filter_cadvisor2mdm plugin" } + @log = Logger.new(@log_path, 1, 5000000) + @log.debug { "Starting filter_cadvisor2mdm plugin" } end end - def start(env=ENV, applicationInsightsUtility=ApplicationInsightsUtility, kubernetesApiClient=KubernetesApiClient, kubeletUtils=KubeletUtils, oms_common=OMS::Common) - @env = env - @AplicationInsightsUtility = applicationInsightsUtility - @KubernetesAPIClient = kubernetesApiClient - @KubeletUtils = kubeletUtils - @oms_common = oms_common - super() - - @@hostName = (@oms_common.get_hostname) - - @@isWindows = false - @@os_type = @env["OS_TYPE"] - if !@@os_type.nil? && !@@os_type.empty? && @@os_type.strip.casecmp("windows") == 0 - @@isWindows = true - end - + def start + super begin - @process_incoming_stream = CustomMetricsUtils.check_custom_metrics_availability(env=@env) - @metrics_to_collect_hash = build_metrics_hash(@metrics_to_collect) - @Log.debug "After check_custom_metrics_availability process_incoming_stream #{@process_incoming_stream}" + @process_incoming_stream = CustomMetricsUtils.check_custom_metrics_availability + @metrics_to_collect_hash = build_metrics_hash + @log.debug "After check_custom_metrics_availability process_incoming_stream #{@process_incoming_stream}" @@containerResourceUtilTelemetryTimeTracker = DateTime.now.to_time.to_i @@pvUsageTelemetryTimeTracker = DateTime.now.to_time.to_i @@ -81,19 +74,19 @@ def start(env=ENV, applicationInsightsUtility=ApplicationInsightsUtility, kubern @containerMemoryLimitHash = {} @containerResourceDimensionHash = {} @pvUsageHash = {} - @@metric_threshold_hash = MdmMetricsGenerator.getContainerResourceUtilizationThresholds(env=@env) + @@metric_threshold_hash = MdmMetricsGenerator.getContainerResourceUtilizationThresholds @NodeCache = Fluent::Plugin::NodeStatsCache.new() end rescue => e - @Log.info "Error initializing plugin #{e}" + @log.info "Error initializing plugin #{e}" end end - def build_metrics_hash metrics_to_collect_list - @Log.debug "Building Hash of Metrics to Collect" - metrics_to_collect_arr = metrics_to_collect_list.split(",").map(&:strip) + def build_metrics_hash + @log.debug "Building Hash of Metrics to Collect" + metrics_to_collect_arr = @metrics_to_collect.split(",").map(&:strip) metrics_hash = metrics_to_collect_arr.map { |x| [x.downcase, true] }.to_h - @Log.info "Metrics Collected : #{metrics_hash}" + @log.info "Metrics Collected : #{metrics_hash}" return metrics_hash end @@ -113,8 +106,8 @@ def setThresholdExceededTelemetry(metricName) @pvExceededUsageThreshold = true end rescue => errorStr - @Log.info "Error in setThresholdExceededTelemetry: #{errorStr}" - @ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) + @log.info "Error in setThresholdExceededTelemetry: #{errorStr}" + ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) end end @@ -132,15 +125,15 @@ def flushMetricTelemetry properties["CpuThresholdExceededInLastFlushInterval"] = @containersExceededCpuThreshold properties["MemRssThresholdExceededInLastFlushInterval"] = @containersExceededMemRssThreshold properties["MemWSetThresholdExceededInLastFlushInterval"] = @containersExceededMemWorkingSetThreshold - @ApplicationInsightsUtility.sendCustomEvent(Constants::CONTAINER_RESOURCE_UTIL_HEART_BEAT_EVENT, properties) + ApplicationInsightsUtility.sendCustomEvent(Constants::CONTAINER_RESOURCE_UTIL_HEART_BEAT_EVENT, properties) @containersExceededCpuThreshold = false @containersExceededMemRssThreshold = false @containersExceededMemWorkingSetThreshold = false @@containerResourceUtilTelemetryTimeTracker = DateTime.now.to_time.to_i end rescue => errorStr - @Log.info "Error in flushMetricTelemetry: #{errorStr} for container resource util telemetry" - @ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) + @log.info "Error in flushMetricTelemetry: #{errorStr} for container resource util telemetry" + ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) end # Also send for PV usage metrics @@ -152,14 +145,14 @@ def flushMetricTelemetry pvProperties = {} pvProperties["PVUsageThresholdPercentage"] = @@metric_threshold_hash[Constants::PV_USED_BYTES] pvProperties["PVUsageThresholdExceededInLastFlushInterval"] = @pvExceededUsageThreshold - @ApplicationInsightsUtility.sendCustomEvent(Constants::PV_USAGE_HEART_BEAT_EVENT, pvProperties) + ApplicationInsightsUtility.sendCustomEvent(Constants::PV_USAGE_HEART_BEAT_EVENT, pvProperties) @pvExceededUsageThreshold = false @@pvUsageTelemetryTimeTracker = DateTime.now.to_time.to_i end end rescue => errorStr - @Log.info "Error in flushMetricTelemetry: #{errorStr} for PV usage telemetry" - @ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) + @log.info "Error in flushMetricTelemetry: #{errorStr} for PV usage telemetry" + ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) end end @@ -191,7 +184,7 @@ def filter(tag, time, record) target_node_cpu_capacity_mc = @cpu_capacity target_node_cpu_allocatable_mc = @cpu_allocatable end - @Log.info "Metric_value: #{metric_value} CPU Capacity #{target_node_cpu_capacity_mc} CPU Allocatable #{target_node_cpu_allocatable_mc} " + @log.info "Metric_value: #{metric_value} CPU Capacity #{target_node_cpu_capacity_mc} CPU Allocatable #{target_node_cpu_allocatable_mc} " if target_node_cpu_capacity_mc != 0.0 percentage_metric_value = (metric_value) * 100 / target_node_cpu_capacity_mc end @@ -212,7 +205,7 @@ def filter(tag, time, record) target_node_mem_allocatable = @memory_allocatable # We do not need this value in the replicaset end - @Log.info "Metric_value: #{metric_value} Memory Capacity #{target_node_mem_capacity} Memory Allocatable #{target_node_mem_allocatable}" + @log.info "Metric_value: #{metric_value} Memory Capacity #{target_node_mem_capacity} Memory Allocatable #{target_node_mem_allocatable}" if target_node_mem_capacity != 0.0 percentage_metric_value = metric_value * 100 / target_node_mem_capacity end @@ -223,7 +216,7 @@ def filter(tag, time, record) allocatable_percentage_metric_value = 0.0 end end - @Log.info "percentage_metric_value for metric: #{metric_name} for instance: #{record["Host"]} percentage: #{percentage_metric_value} allocatable_percentage: #{allocatable_percentage_metric_value}" + @log.info "percentage_metric_value for metric: #{metric_name} for instance: #{record["Host"]} percentage: #{percentage_metric_value} allocatable_percentage: #{allocatable_percentage_metric_value}" # do some sanity checking. if percentage_metric_value > 100.0 @@ -231,14 +224,14 @@ def filter(tag, time, record) telemetryProperties["Computer"] = record["Host"] telemetryProperties["MetricName"] = metric_name telemetryProperties["MetricPercentageValue"] = percentage_metric_value - @ApplicationInsightsUtility.sendCustomEvent("ErrorPercentageOutOfBounds", telemetryProperties) + ApplicationInsightsUtility.sendCustomEvent("ErrorPercentageOutOfBounds", telemetryProperties) end if allocatable_percentage_metric_value > 100.0 telemetryProperties = {} telemetryProperties["Computer"] = record["Host"] telemetryProperties["MetricName"] = metric_name telemetryProperties["MetricAllocatablePercentageValue"] = allocatable_percentage_metric_value - @ApplicationInsightsUtility.sendCustomEvent("ErrorPercentageOutOfBounds", telemetryProperties) + ApplicationInsightsUtility.sendCustomEvent("ErrorPercentageOutOfBounds", telemetryProperties) end return MdmMetricsGenerator.getNodeResourceMetricRecords(record, metric_name, metric_value, percentage_metric_value, allocatable_percentage_metric_value) @@ -270,8 +263,8 @@ def filter(tag, time, record) end # Send this metric only if resource utilization is greater than configured threshold - @Log.info "percentage_metric_value for metric: #{metricName} for instance: #{instanceName} percentage: #{percentage_metric_value}" - @Log.info "@@metric_threshold_hash for #{metricName}: #{@@metric_threshold_hash[metricName]}" + @log.info "percentage_metric_value for metric: #{metricName} for instance: #{instanceName} percentage: #{percentage_metric_value}" + @log.info "@@metric_threshold_hash for #{metricName}: #{@@metric_threshold_hash[metricName]}" thresholdPercentage = @@metric_threshold_hash[metricName] # Flushing telemetry here since, we return as soon as we generate the metric @@ -293,8 +286,8 @@ def filter(tag, time, record) return [] end #end if block for process incoming stream check rescue Exception => e - @Log.info "Error processing cadvisor record Exception: #{e.class} Message: #{e.message}" - @ApplicationInsightsUtility.sendExceptionTelemetry(e.backtrace) + @log.info "Error processing cadvisor record Exception: #{e.class} Message: #{e.message}" + ApplicationInsightsUtility.sendExceptionTelemetry(e.backtrace) return [] #return empty array if we ran into any errors end end @@ -309,8 +302,8 @@ def filterPVInsightsMetrics(record) if capacity != 0 percentage_metric_value = (usage * 100.0) / capacity end - @Log.info "percentage_metric_value for metric: #{metricName} percentage: #{percentage_metric_value}" - @Log.info "@@metric_threshold_hash for #{metricName}: #{@@metric_threshold_hash[metricName]}" + @log.info "percentage_metric_value for metric: #{metricName} percentage: #{percentage_metric_value}" + @log.info "@@metric_threshold_hash for #{metricName}: #{@@metric_threshold_hash[metricName]}" computer = record["Computer"] resourceDimensions = record["Tags"] @@ -331,60 +324,60 @@ def filterPVInsightsMetrics(record) end # end if block for dataItem name check return [] rescue Exception => e - @Log.info "Error processing cadvisor insights metrics record Exception: #{e.class} Message: #{e.message}" - @ApplicationInsightsUtility.sendExceptionTelemetry(e.backtrace) + @log.info "Error processing cadvisor insights metrics record Exception: #{e.class} Message: #{e.message}" + ApplicationInsightsUtility.sendExceptionTelemetry(e.backtrace) return [] #return empty array if we ran into any errors end end def ensure_cpu_memory_capacity_and_allocatable_set - @@controller_type = @env["CONTROLLER_TYPE"] + @@controller_type = ENV["CONTROLLER_TYPE"] if @cpu_capacity != 0.0 && @memory_capacity != 0.0 && @@controller_type.downcase == "replicaset" - @Log.info "CPU And Memory Capacity are already set and their values are as follows @cpu_capacity : #{@cpu_capacity}, @memory_capacity: #{@memory_capacity}" + @log.info "CPU And Memory Capacity are already set and their values are as follows @cpu_capacity : #{@cpu_capacity}, @memory_capacity: #{@memory_capacity}" return end if @@controller_type.downcase == "daemonset" && @cpu_capacity != 0.0 && @memory_capacity != 0.0 && @cpu_allocatable != 0.0 && @memory_allocatable != 0.0 - @Log.info "CPU And Memory Capacity are already set and their values are as follows @cpu_capacity : #{@cpu_capacity}, @memory_capacity: #{@memory_capacity}" - @Log.info "CPU And Memory Allocatable are already set and their values are as follows @cpu_allocatable : #{@cpu_allocatable}, @memory_allocatable: #{@memory_allocatable}" + @log.info "CPU And Memory Capacity are already set and their values are as follows @cpu_capacity : #{@cpu_capacity}, @memory_capacity: #{@memory_capacity}" + @log.info "CPU And Memory Allocatable are already set and their values are as follows @cpu_allocatable : #{@cpu_allocatable}, @memory_allocatable: #{@memory_allocatable}" return end if @@controller_type.downcase == "replicaset" - @Log.info "ensure_cpu_memory_capacity_set @cpu_capacity #{@cpu_capacity} @memory_capacity #{@memory_capacity}" + @log.info "ensure_cpu_memory_capacity_set @cpu_capacity #{@cpu_capacity} @memory_capacity #{@memory_capacity}" begin - resourceUri = @KubernetesAPIClient.getNodesResourceUri("nodes?fieldSelector=metadata.name%3D#{@@hostName}") - nodeInventory = JSON.parse(@KubernetesAPIClient.getKubeResourceInfo(resourceUri).body) + resourceUri = KubernetesApiClient.getNodesResourceUri("nodes?fieldSelector=metadata.name%3D#{@@hostName}") + nodeInventory = JSON.parse(KubernetesApiClient.getKubeResourceInfo(resourceUri).body) rescue Exception => e - @Log.info "Error when getting nodeInventory from kube API. Exception: #{e.class} Message: #{e.message} " - @ApplicationInsightsUtility.sendExceptionTelemetry(e.backtrace) + @log.info "Error when getting nodeInventory from kube API. Exception: #{e.class} Message: #{e.message} " + ApplicationInsightsUtility.sendExceptionTelemetry(e.backtrace) end if !nodeInventory.nil? - cpu_capacity_json = @KubernetesAPIClient.parseNodeLimits(nodeInventory, "capacity", "cpu", "cpuCapacityNanoCores") + cpu_capacity_json = KubernetesApiClient.parseNodeLimits(nodeInventory, "capacity", "cpu", "cpuCapacityNanoCores") if !cpu_capacity_json.nil? metricVal = JSON.parse(cpu_capacity_json[0]["json_Collections"])[0]["Value"] if !metricVal.to_s.nil? @cpu_capacity = metricVal - @Log.info "CPU Limit #{@cpu_capacity}" + @log.info "CPU Limit #{@cpu_capacity}" end else - @Log.info "Error getting cpu_capacity" + @log.info "Error getting cpu_capacity" end - memory_capacity_json = @KubernetesAPIClient.parseNodeLimits(nodeInventory, "capacity", "memory", "memoryCapacityBytes") + memory_capacity_json = KubernetesApiClient.parseNodeLimits(nodeInventory, "capacity", "memory", "memoryCapacityBytes") if !memory_capacity_json.nil? metricVal = JSON.parse(cpu_capacity_json[0]["json_Collections"])[0]["Value"] if !metricVal.to_s.nil? @memory_capacity = metricVal - @Log.info "Memory Limit #{@memory_capacity}" + @log.info "Memory Limit #{@memory_capacity}" end else - @Log.info "Error getting memory_capacity" + @log.info "Error getting memory_capacity" end end elsif @@controller_type.downcase == "daemonset" - capacity_from_kubelet = @KubeletUtils.get_node_capacity + capacity_from_kubelet = KubeletUtils.get_node_capacity # Error handling in case /metrics/cadvsior endpoint fails if !capacity_from_kubelet.nil? && capacity_from_kubelet.length > 1 @@ -392,10 +385,10 @@ def ensure_cpu_memory_capacity_and_allocatable_set @memory_capacity = capacity_from_kubelet[1] else # cpu_capacity and memory_capacity keep initialized value of 0.0 - @Log.error "Error getting capacity_from_kubelet: cpu_capacity and memory_capacity" + @log.error "Error getting capacity_from_kubelet: cpu_capacity and memory_capacity" end - allocatable_from_kubelet = @KubeletUtils.get_node_allocatable(@cpu_capacity, @memory_capacity) + allocatable_from_kubelet = KubeletUtils.get_node_allocatable(@cpu_capacity, @memory_capacity) # Error handling in case /configz endpoint fails if !allocatable_from_kubelet.nil? && allocatable_from_kubelet.length > 1 @@ -403,7 +396,7 @@ def ensure_cpu_memory_capacity_and_allocatable_set @memory_allocatable = allocatable_from_kubelet[1] else # cpu_allocatable and memory_allocatable keep initialized value of 0.0 - @Log.error "Error getting allocatable_from_kubelet: cpu_allocatable and memory_allocatable" + @log.error "Error getting allocatable_from_kubelet: cpu_allocatable and memory_allocatable" end end end @@ -414,7 +407,7 @@ def filter_stream(tag, es) ensure_cpu_memory_capacity_and_allocatable_set # Getting container limits hash if @process_incoming_stream - @containerCpuLimitHash, @containerMemoryLimitHash, @containerResourceDimensionHash = KubeletUtils.get_all_container_limits # TODO: mock this + @containerCpuLimitHash, @containerMemoryLimitHash, @containerResourceDimensionHash = KubeletUtils.get_all_container_limits end es.each { |time, record| @@ -424,7 +417,7 @@ def filter_stream(tag, es) } if filtered_records } rescue => e - @Log.info "Error in filter_stream #{e.message}" + @log.info "Error in filter_stream #{e.message}" end new_es end diff --git a/source/plugins/ruby/filter_cadvisor2mdm_test.rb b/source/plugins/ruby/filter_cadvisor2mdm_test.rb index 2cc207200..bfb9ea51b 100644 --- a/source/plugins/ruby/filter_cadvisor2mdm_test.rb +++ b/source/plugins/ruby/filter_cadvisor2mdm_test.rb @@ -1,120 +1,118 @@ -require 'minitest/autorun' -require 'fluent/test' -require 'fluent/test/driver/filter' -require 'fluent/test/helpers' -require_relative 'filter_cadvisor2mdm.rb' -require_relative 'KubernetesApiClient' -require 'byebug' - - -# This is one way to stub a class. It's longer than the method demonstrated in in_kube_nodes_test.rb but gives more control -# over how the stub behaves -class Ai_utility_stub - class << self - def sendCustomEvent(a, b) - end - - def sendExceptionTelemetry (errorstr) - # this shouldn't happen, why was there an exception? - byebug - end - end -end - -class KubernetesApiClientMock < KubernetesApiClient - class GetNodesResponse - def body - return File.open("test/unit-tests/canned-api-responses/get_nodes_response_2.json").read - end - end - class << self - def getKubeResourceInfo(resource, api_group: nil) - if resource == "nodes?fieldSelector=metadata.name%3DWIN-T14B9CT7KMS" - return GetNodesResponse.new() - end - # this means that a saved input is missing - byebug - end - end -end - - - -class FilterCadvisor2MdmTests < Minitest::Test - include Fluent::Test::Helpers - - def setup - Fluent::Test.setup - end +# require 'minitest/autorun' +# require 'fluent/test' +# require 'fluent/test/driver/filter' +# require 'fluent/test/helpers' +# require_relative 'filter_cadvisor2mdm.rb' +# require_relative 'KubernetesApiClient' +# require 'byebug' + + +# # This is one way to stub a class. It's longer than the method demonstrated in in_kube_nodes_test.rb but gives more control +# # over how the stub behaves +# class Ai_utility_stub +# class << self +# def sendCustomEvent(a, b) +# end + +# def sendExceptionTelemetry (errorstr) +# # this shouldn't happen, why was there an exception? +# byebug +# end +# end +# end + +# class KubernetesApiClientMock < KubernetesApiClient +# class GetNodesResponse +# def body +# return File.open("test/unit-tests/canned-api-responses/get_nodes_response_2.json").read +# end +# end +# class << self +# def getKubeResourceInfo(resource, api_group: nil) +# if resource == "nodes?fieldSelector=metadata.name%3DWIN-T14B9CT7KMS" +# return GetNodesResponse.new() +# end +# # this means that a saved input is missing +# byebug +# end +# end +# end + + + +# class FilterCadvisor2MdmTests < Minitest::Test +# include Fluent::Test::Helpers + +# def setup +# Fluent::Test.setup +# end - def create_driver(conf = "") - Fluent::Test::Driver::Filter.new(Fluent::Plugin::CAdvisor2MdmFilter).configure(conf) - end +# def create_driver(conf = "") +# Fluent::Test::Driver::Filter.new(Fluent::Plugin::CAdvisor2MdmFilter).configure(conf) +# end - # A relatively simple test for a helper method - def test_build_metrics_hash - instance = create_driver.instance - - expected = {"constants::cpu_usage_nano_cores" => true, "constants::memory_working_set_bytes" => true, "constants::memory_rss_bytes"=> true, "constants::pv_used_bytes"=> true} - actual = instance.build_metrics_hash "Constants::CPU_USAGE_NANO_CORES,Constants::MEMORY_WORKING_SET_BYTES,Constants::MEMORY_RSS_BYTES,Constants::PV_USED_BYTES" - assert_equal(expected, actual) - - assert_equal({}, instance.build_metrics_hash("")) - - assert_equal({"test_input:.<>" => true}, instance.build_metrics_hash("test_input:.<>")) - - end - - - # a much more complicated test for the filter method of filter_cadvisor2mdm (this is an allup test) - def test_filter - - - env = {"CONTROLLER_TYPE" => "ReplicaSet", - "OS_TYPE" => "linux", - "AZMON_ALERT_CONTAINER_CPU_THRESHOLD" => Constants::DEFAULT_MDM_CPU_UTILIZATION_THRESHOLD.to_s, - "AZMON_ALERT_CONTAINER_MEMORY_RSS_THRESHOLD" => Constants::DEFAULT_MDM_MEMORY_RSS_THRESHOLD.to_s, - "AZMON_ALERT_CONTAINER_MEMORY_WORKING_SET_THRESHOLD" => Constants::DEFAULT_MDM_MEMORY_WORKING_SET_THRESHOLD.to_s, - "AZMON_ALERT_PV_USAGE_THRESHOLD" => Constants::DEFAULT_MDM_PV_UTILIZATION_THRESHOLD.to_s, - "AZMON_ALERT_JOB_COMPLETION_TIME_THRESHOLD" => Constants::DEFAULT_MDM_JOB_COMPLETED_TIME_THRESHOLD_MINUTES.to_s, - "AKS_REGION" => "westus2", - "AKS_RESOURCE_ID" => "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/rg/providers/Microsoft.ContainerService/managedClusters/clustername", - "CLOUD_ENVIRONMENT" => "azurepubliccloud"} # TODO: this is actually set to public in running containers. Figure out how @process_incoming_stream resolves to true - applicationInsightsUtility = Ai_utility_stub.new() - kubernetesApiClient = KubernetesApiClientMock - - oms_common = Minitest::Mock.new - oms_common.expect(:get_hostname, "aks-nodepool1-24816391-vmss000000") - - config = %[ - metrics_to_collect cpuUsageNanoCores,memoryWorkingSetBytes,pvUsedBytes - @log_level info - ] - - data = [ - {"tag" => "mdm.cadvisorperf", "time" => 1629337471, "data" => {"Timestamp"=>"2021-08-19T01:44:31Z", "Host"=>"aks-nodepool1-24031368-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"/subscriptions/9b96ebbd-c57a-42d1-bbe9-b69296e4c7fb/resourceGroups/davidbuild1/providers/Microsoft.ContainerService/managedClusters/davidbuild1/aks-nodepool1-24031368-vmss000000", "json_Collections"=>"[{\"CounterName\":\"memoryRssBytes\",\"Value\":511778816}]"}} - ] - - expected_output = [ - {"time"=>"2021-08-19T01:44:31Z", "data"=>{"baseData"=>{"metric"=>"memoryRssBytes", "namespace"=>"Insights.Container/nodes", "dimNames"=>["host"], "series"=>[{"dimValues"=>["aks-nodepool1-24031368-vmss000000"], "min"=>511778816, "max"=>511778816, "sum"=>511778816, "count"=>1}]}}}, - {"time"=>"2021-08-19T01:44:31Z", "data"=>{"baseData"=>{"metric"=>"memoryRssPercentage", "namespace"=>"Insights.Container/nodes", "dimNames"=>["host"], "series"=>[{"dimValues"=>["aks-nodepool1-24031368-vmss000000"], "min"=>7.018830955074673, "max"=>7.018830955074673, "sum"=>7.018830955074673, "count"=>1}]}}} - ] - - d = create_driver(config) - # TODO: why doesn't the fluentd test harness call start automatically? - d.instance.start(env=env, applicationInsightsUtility=applicationInsightsUtility, kubernetesApiClient=kubernetesApiClient, oms_common=oms_common) - time = event_time - - # byebug - d.run do - d.feed(data[0]["tag"], time, data[0]["data"]) - end - - puts d.filtered_records.size - puts d.filtered_records - - assert_equal(0, d.filtered_records.size) - # assert_equal("expected response", d.filtered_records) - end - -end \ No newline at end of file +# # A relatively simple test for a helper method +# def test_build_metrics_hash +# instance = create_driver.instance + +# expected = {"constants::cpu_usage_nano_cores" => true, "constants::memory_working_set_bytes" => true, "constants::memory_rss_bytes"=> true, "constants::pv_used_bytes"=> true} +# actual = instance.build_metrics_hash "Constants::CPU_USAGE_NANO_CORES,Constants::MEMORY_WORKING_SET_BYTES,Constants::MEMORY_RSS_BYTES,Constants::PV_USED_BYTES" +# assert_equal(expected, actual) + +# assert_equal({}, instance.build_metrics_hash("")) + +# assert_equal({"test_input:.<>" => true}, instance.build_metrics_hash("test_input:.<>")) +# end + + +# # a much more complicated test for the filter method of filter_cadvisor2mdm (this is an allup test) +# def test_filter + + +# env = {"CONTROLLER_TYPE" => "ReplicaSet", +# "OS_TYPE" => "linux", +# "AZMON_ALERT_CONTAINER_CPU_THRESHOLD" => Constants::DEFAULT_MDM_CPU_UTILIZATION_THRESHOLD.to_s, +# "AZMON_ALERT_CONTAINER_MEMORY_RSS_THRESHOLD" => Constants::DEFAULT_MDM_MEMORY_RSS_THRESHOLD.to_s, +# "AZMON_ALERT_CONTAINER_MEMORY_WORKING_SET_THRESHOLD" => Constants::DEFAULT_MDM_MEMORY_WORKING_SET_THRESHOLD.to_s, +# "AZMON_ALERT_PV_USAGE_THRESHOLD" => Constants::DEFAULT_MDM_PV_UTILIZATION_THRESHOLD.to_s, +# "AZMON_ALERT_JOB_COMPLETION_TIME_THRESHOLD" => Constants::DEFAULT_MDM_JOB_COMPLETED_TIME_THRESHOLD_MINUTES.to_s, +# "AKS_REGION" => "westus2", +# "AKS_RESOURCE_ID" => "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/rg/providers/Microsoft.ContainerService/managedClusters/clustername", +# "CLOUD_ENVIRONMENT" => "azurepubliccloud"} # TODO: this is actually set to public in running containers. Figure out how @process_incoming_stream resolves to true +# applicationInsightsUtility = Ai_utility_stub.new() +# kubernetesApiClient = KubernetesApiClientMock + +# oms_common = Minitest::Mock.new +# oms_common.expect(:get_hostname, "aks-nodepool1-24816391-vmss000000") + +# config = %[ +# metrics_to_collect cpuUsageNanoCores,memoryWorkingSetBytes,pvUsedBytes +# @log_level info +# ] + +# data = [ +# {"tag" => "mdm.cadvisorperf", "time" => 1629337471, "data" => {"Timestamp"=>"2021-08-19T01:44:31Z", "Host"=>"aks-nodepool1-24031368-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"/subscriptions/9b96ebbd-c57a-42d1-bbe9-b69296e4c7fb/resourceGroups/davidbuild1/providers/Microsoft.ContainerService/managedClusters/davidbuild1/aks-nodepool1-24031368-vmss000000", "json_Collections"=>"[{\"CounterName\":\"memoryRssBytes\",\"Value\":511778816}]"}} +# ] + +# expected_output = [ +# {"time"=>"2021-08-19T01:44:31Z", "data"=>{"baseData"=>{"metric"=>"memoryRssBytes", "namespace"=>"Insights.Container/nodes", "dimNames"=>["host"], "series"=>[{"dimValues"=>["aks-nodepool1-24031368-vmss000000"], "min"=>511778816, "max"=>511778816, "sum"=>511778816, "count"=>1}]}}}, +# {"time"=>"2021-08-19T01:44:31Z", "data"=>{"baseData"=>{"metric"=>"memoryRssPercentage", "namespace"=>"Insights.Container/nodes", "dimNames"=>["host"], "series"=>[{"dimValues"=>["aks-nodepool1-24031368-vmss000000"], "min"=>7.018830955074673, "max"=>7.018830955074673, "sum"=>7.018830955074673, "count"=>1}]}}} +# ] + +# d = create_driver(config) +# # TODO: why doesn't the fluentd test harness call start automatically? +# d.instance.start(env=env, applicationInsightsUtility=applicationInsightsUtility, kubernetesApiClient=kubernetesApiClient, oms_common=oms_common) +# time = event_time + +# # byebug +# d.run do +# d.feed(data[0]["tag"], time, data[0]["data"]) +# end + +# puts d.filtered_records.size +# puts d.filtered_records + +# assert_equal(0, d.filtered_records.size) +# # assert_equal("expected response", d.filtered_records) +# end +# end diff --git a/source/plugins/ruby/kubelet_utils.rb b/source/plugins/ruby/kubelet_utils.rb index fca67eb5e..f5ee1e57c 100644 --- a/source/plugins/ruby/kubelet_utils.rb +++ b/source/plugins/ruby/kubelet_utils.rb @@ -214,6 +214,9 @@ def get_all_container_limits @log.info "Error in get_all_container_limits: #{errorStr}" ApplicationInsightsUtility.sendExceptionTelemetry(errorStr) end + @log.info "containerCpuLimitHash: #{containerCpuLimitHash}" + @log.info "containerMemoryLimitHash: #{containerMemoryLimitHash}" + @log.info "containerResourceDimensionHash: #{containerResourceDimensionHash}" return [containerCpuLimitHash, containerMemoryLimitHash, containerResourceDimensionHash] end From a05b1de1b4abd309846921e1fc0b5190cd9fdf52 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Mon, 23 Aug 2021 13:00:08 -0700 Subject: [PATCH 26/33] cleanup --- .../plugins/ruby/filter_cadvisor2mdm_test.rb | 118 ------------------ source/plugins/ruby/in_kube_nodes.rb | 13 +- source/plugins/ruby/in_kube_nodes_test.rb | 9 +- source/plugins/ruby/kubelet_utils.rb | 4 +- 4 files changed, 12 insertions(+), 132 deletions(-) delete mode 100644 source/plugins/ruby/filter_cadvisor2mdm_test.rb diff --git a/source/plugins/ruby/filter_cadvisor2mdm_test.rb b/source/plugins/ruby/filter_cadvisor2mdm_test.rb deleted file mode 100644 index bfb9ea51b..000000000 --- a/source/plugins/ruby/filter_cadvisor2mdm_test.rb +++ /dev/null @@ -1,118 +0,0 @@ -# require 'minitest/autorun' -# require 'fluent/test' -# require 'fluent/test/driver/filter' -# require 'fluent/test/helpers' -# require_relative 'filter_cadvisor2mdm.rb' -# require_relative 'KubernetesApiClient' -# require 'byebug' - - -# # This is one way to stub a class. It's longer than the method demonstrated in in_kube_nodes_test.rb but gives more control -# # over how the stub behaves -# class Ai_utility_stub -# class << self -# def sendCustomEvent(a, b) -# end - -# def sendExceptionTelemetry (errorstr) -# # this shouldn't happen, why was there an exception? -# byebug -# end -# end -# end - -# class KubernetesApiClientMock < KubernetesApiClient -# class GetNodesResponse -# def body -# return File.open("test/unit-tests/canned-api-responses/get_nodes_response_2.json").read -# end -# end -# class << self -# def getKubeResourceInfo(resource, api_group: nil) -# if resource == "nodes?fieldSelector=metadata.name%3DWIN-T14B9CT7KMS" -# return GetNodesResponse.new() -# end -# # this means that a saved input is missing -# byebug -# end -# end -# end - - - -# class FilterCadvisor2MdmTests < Minitest::Test -# include Fluent::Test::Helpers - -# def setup -# Fluent::Test.setup -# end - -# def create_driver(conf = "") -# Fluent::Test::Driver::Filter.new(Fluent::Plugin::CAdvisor2MdmFilter).configure(conf) -# end - -# # A relatively simple test for a helper method -# def test_build_metrics_hash -# instance = create_driver.instance - -# expected = {"constants::cpu_usage_nano_cores" => true, "constants::memory_working_set_bytes" => true, "constants::memory_rss_bytes"=> true, "constants::pv_used_bytes"=> true} -# actual = instance.build_metrics_hash "Constants::CPU_USAGE_NANO_CORES,Constants::MEMORY_WORKING_SET_BYTES,Constants::MEMORY_RSS_BYTES,Constants::PV_USED_BYTES" -# assert_equal(expected, actual) - -# assert_equal({}, instance.build_metrics_hash("")) - -# assert_equal({"test_input:.<>" => true}, instance.build_metrics_hash("test_input:.<>")) -# end - - -# # a much more complicated test for the filter method of filter_cadvisor2mdm (this is an allup test) -# def test_filter - - -# env = {"CONTROLLER_TYPE" => "ReplicaSet", -# "OS_TYPE" => "linux", -# "AZMON_ALERT_CONTAINER_CPU_THRESHOLD" => Constants::DEFAULT_MDM_CPU_UTILIZATION_THRESHOLD.to_s, -# "AZMON_ALERT_CONTAINER_MEMORY_RSS_THRESHOLD" => Constants::DEFAULT_MDM_MEMORY_RSS_THRESHOLD.to_s, -# "AZMON_ALERT_CONTAINER_MEMORY_WORKING_SET_THRESHOLD" => Constants::DEFAULT_MDM_MEMORY_WORKING_SET_THRESHOLD.to_s, -# "AZMON_ALERT_PV_USAGE_THRESHOLD" => Constants::DEFAULT_MDM_PV_UTILIZATION_THRESHOLD.to_s, -# "AZMON_ALERT_JOB_COMPLETION_TIME_THRESHOLD" => Constants::DEFAULT_MDM_JOB_COMPLETED_TIME_THRESHOLD_MINUTES.to_s, -# "AKS_REGION" => "westus2", -# "AKS_RESOURCE_ID" => "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/rg/providers/Microsoft.ContainerService/managedClusters/clustername", -# "CLOUD_ENVIRONMENT" => "azurepubliccloud"} # TODO: this is actually set to public in running containers. Figure out how @process_incoming_stream resolves to true -# applicationInsightsUtility = Ai_utility_stub.new() -# kubernetesApiClient = KubernetesApiClientMock - -# oms_common = Minitest::Mock.new -# oms_common.expect(:get_hostname, "aks-nodepool1-24816391-vmss000000") - -# config = %[ -# metrics_to_collect cpuUsageNanoCores,memoryWorkingSetBytes,pvUsedBytes -# @log_level info -# ] - -# data = [ -# {"tag" => "mdm.cadvisorperf", "time" => 1629337471, "data" => {"Timestamp"=>"2021-08-19T01:44:31Z", "Host"=>"aks-nodepool1-24031368-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"/subscriptions/9b96ebbd-c57a-42d1-bbe9-b69296e4c7fb/resourceGroups/davidbuild1/providers/Microsoft.ContainerService/managedClusters/davidbuild1/aks-nodepool1-24031368-vmss000000", "json_Collections"=>"[{\"CounterName\":\"memoryRssBytes\",\"Value\":511778816}]"}} -# ] - -# expected_output = [ -# {"time"=>"2021-08-19T01:44:31Z", "data"=>{"baseData"=>{"metric"=>"memoryRssBytes", "namespace"=>"Insights.Container/nodes", "dimNames"=>["host"], "series"=>[{"dimValues"=>["aks-nodepool1-24031368-vmss000000"], "min"=>511778816, "max"=>511778816, "sum"=>511778816, "count"=>1}]}}}, -# {"time"=>"2021-08-19T01:44:31Z", "data"=>{"baseData"=>{"metric"=>"memoryRssPercentage", "namespace"=>"Insights.Container/nodes", "dimNames"=>["host"], "series"=>[{"dimValues"=>["aks-nodepool1-24031368-vmss000000"], "min"=>7.018830955074673, "max"=>7.018830955074673, "sum"=>7.018830955074673, "count"=>1}]}}} -# ] - -# d = create_driver(config) -# # TODO: why doesn't the fluentd test harness call start automatically? -# d.instance.start(env=env, applicationInsightsUtility=applicationInsightsUtility, kubernetesApiClient=kubernetesApiClient, oms_common=oms_common) -# time = event_time - -# # byebug -# d.run do -# d.feed(data[0]["tag"], time, data[0]["data"]) -# end - -# puts d.filtered_records.size -# puts d.filtered_records - -# assert_equal(0, d.filtered_records.size) -# # assert_equal("expected response", d.filtered_records) -# end -# end diff --git a/source/plugins/ruby/in_kube_nodes.rb b/source/plugins/ruby/in_kube_nodes.rb index 38021f4e4..32ca499b1 100644 --- a/source/plugins/ruby/in_kube_nodes.rb +++ b/source/plugins/ruby/in_kube_nodes.rb @@ -7,7 +7,11 @@ module Fluent::Plugin class Kube_nodeInventory_Input < Input Fluent::Plugin.register_input("kube_nodes", self) - def initialize (kubernetesApiClient=nil, applicationInsightsUtility=nil, extensionUtils=nil, env=nil) + def initialize (kubernetesApiClient=nil, + applicationInsightsUtility=nil, + extensionUtils=nil, + env=nil, + TELEMETRY_FLUSH_INTERVAL_IN_MINUTES=Constants::TELEMETRY_FLUSH_INTERVAL_IN_MINUTES) super() require "yaml" @@ -62,7 +66,7 @@ def initialize (kubernetesApiClient=nil, applicationInsightsUtility=nil, extensi @NodeCache = NodeStatsCache.new() # this is so that telemetry can be unit tested in a reasonable amount of time - @TELEMETRY_FLUSH_INTERVAL_IN_MINUTES = Constants::TELEMETRY_FLUSH_INTERVAL_IN_MINUTES + @TELEMETRY_FLUSH_INTERVAL_IN_MINUTES = TELEMETRY_FLUSH_INTERVAL_IN_MINUTES end config_param :run_interval, :time, :default => 60 @@ -570,11 +574,6 @@ def getNodeTelemetryProps(item) end return properties end - - # this is used in - def set_telemetry_flush_interval(interval) - @TELEMETRY_FLUSH_INTERVAL_IN_MINUTES = interval - end end # Kube_Node_Input diff --git a/source/plugins/ruby/in_kube_nodes_test.rb b/source/plugins/ruby/in_kube_nodes_test.rb index f148c8009..fffaebf72 100644 --- a/source/plugins/ruby/in_kube_nodes_test.rb +++ b/source/plugins/ruby/in_kube_nodes_test.rb @@ -21,7 +21,7 @@ def create_driver(conf = {}, kubernetesApiClient=nil, applicationInsightsUtility env=env)).configure(conf) end - def overwrite_collection_time(data) + def overwrite_collection_time(data) if data.key?("CollectionTime") data["CollectionTime"] = "~CollectionTime~" end @@ -75,7 +75,7 @@ def extensionUtils.isAADMSIAuthMode if expected_responses.key?([tag, cleaned_record]) expected_responses[[tag, cleaned_record]] = true else - assert_equal(true, false) + assert_equal(true, false) end end @@ -129,14 +129,13 @@ def appInsightsUtil.sendMetricTelemetry(a, b, c) config = "run_interval 999999999" # only run once - d = create_driver(config, kubernetesApiClient=kubeApiClient, applicationInsightsUtility=appInsightsUtil, extensionUtils=extensionUtils, env=env) + d = create_driver(config, kubernetesApiClient=kubeApiClient, applicationInsightsUtility=appInsightsUtil, extensionUtils=extensionUtils, env=env, TELEMETRY_FLUSH_INTERVAL_IN_MINUTES=0) d.instance.start - d.instance.set_telemetry_flush_interval(0) d.instance.enumerate d.run(timeout: 99999) #TODO: is this necessary? - expected_responses = { + expected_responses = { ["oneagent.containerInsights.KUBE_NODE_INVENTORY_BLOB", {"CollectionTime"=>"~CollectionTime~", "Computer"=>"correct-node", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"correct-node", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"}] => false, ["mdm.kubenodeinventory", {"CollectionTime"=>"~CollectionTime~", "Computer"=>"correct-node", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"correct-node", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"}] => false, ["oneagent.containerInsights.CONTAINER_NODE_INVENTORY_BLOB", {"CollectionTime"=>"~CollectionTime~", "Computer"=>"correct-node", "OperatingSystem"=>"Ubuntu 18.04.5 LTS", "DockerVersion"=>"containerd://1.4.4+azure"}] => false, diff --git a/source/plugins/ruby/kubelet_utils.rb b/source/plugins/ruby/kubelet_utils.rb index f5ee1e57c..e31407b54 100644 --- a/source/plugins/ruby/kubelet_utils.rb +++ b/source/plugins/ruby/kubelet_utils.rb @@ -11,9 +11,9 @@ class KubeletUtils @os_type = ENV["OS_TYPE"] if !@os_type.nil? && !@os_type.empty? && @os_type.strip.casecmp("windows") == 0 - @log_path = Constants::WINDOWS_LOG_PATH + "filter_cadvisor2mdm.log" + @log_path = "/etc/omsagentwindows/filter_cadvisor2mdm.log" else - @log_path = Constants::LINUX_LOG_PATH + "filter_cadvisor2mdm.log" + @log_path = "/var/opt/microsoft/docker-cimprov/log/filter_cadvisor2mdm.log" end @log = Logger.new(@log_path, 1, 5000000) From 6d2ce765494a86cc3fc0de92c74228bb8c433140 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Mon, 23 Aug 2021 14:15:33 -0700 Subject: [PATCH 27/33] more cleanup --- .github/workflows/run_unit_tests.yml | 2 +- .gitignore | 2 +- Dev Guide.md | 10 +++++++++- build/windows/Makefile.ps1 | 2 +- source/plugins/go/src/utils.go | 1 - source/plugins/ruby/CustomMetricsUtils.rb | 8 ++++---- source/plugins/ruby/MdmMetricsGenerator.rb | 16 ++++++++-------- source/plugins/ruby/in_kube_nodes.rb | 6 ++---- source/plugins/ruby/in_kube_nodes_test.rb | 4 ++-- source/plugins/ruby/mdm_metrics_generator.log | 1 - .../get_nodes_response_2.json | 1 - test/unit-tests/run_go_tests.sh | 3 +++ test/unit-tests/run_ruby_tests.sh | 1 + 13 files changed, 32 insertions(+), 25 deletions(-) delete mode 100644 source/plugins/ruby/mdm_metrics_generator.log delete mode 100644 test/unit-tests/canned-api-responses/get_nodes_response_2.json diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index 0e5b520c6..f81e3678d 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -23,4 +23,4 @@ jobs: - name: Run unit tests run: | cd ${{ github.workspace }} - ./test/unit-tests/run_ruby_tests.sh \ No newline at end of file + ./test/unit-tests/run_ruby_tests.sh diff --git a/.gitignore b/.gitignore index fc1ada569..b0467519c 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,4 @@ source/plugins/go/src/*.h *_mock.go *_log.txt *.log -*.byebug_history \ No newline at end of file +*.byebug_history diff --git a/Dev Guide.md b/Dev Guide.md index 51a23959e..7057a4afe 100644 --- a/Dev Guide.md +++ b/Dev Guide.md @@ -40,7 +40,7 @@ Mocks are generated with gomock (mockgen). * The command to generate mock files should go in a `//go:generate` comment at the top of the mocked file (see [socket_writer.go](source/plugin/go/src/extension/socket_writer.go) for an example). This way mocks can be generated by the unit test script. * Mocks also go in the same folder as the mocked files. This is unfortunate, but necessary to avoid circular package dependencies (anyone else feel free to figure out how to move mocks to a separate folder) -Using mocks is also a little tricky. In order to mock functions in a package, they must be converted to reciever methods of a struct. This way the struct can be swapped out at runtime to change which implementaions of a method are called. See the example below: +Using mocks is also a little tricky. In order to mock functions in a package with gomock, they must be converted to reciever methods of a struct. This way the struct can be swapped out at runtime to change which implementaions of a method are called. See the example below: ``` // declare all functions to be mocked in this interface @@ -115,3 +115,11 @@ func someUnitTest() { A concrete example of this can be found in [socket_writer.go](source/plugin/go/src/extension/socket_writer.go) and [extension_test.go](source/plugin/go/src/extension/extension_test.go). Again, if anybody has a better way feel free to update this guide. + + +A simpler way to test a specific function is to write wrapper functions. Test code calls the inner function (ReadFileContentsImpl) and product code calls the wrapper function (ReadFileContents). The wrapper function provides any outside state which a unit test would want to control (like a function to read a file). This option makes product code more verbose, but probably easier to read too. Either way is acceptable. +``` +func ReadFileContents(fullPathToFileName string) (string, error) { + return ReadFileContentsImpl(fullPathToFileName, ioutil.ReadFile) +} +``` diff --git a/build/windows/Makefile.ps1 b/build/windows/Makefile.ps1 index c8dacc06f..e397a2315 100644 --- a/build/windows/Makefile.ps1 +++ b/build/windows/Makefile.ps1 @@ -190,4 +190,4 @@ Write-Host("successfully copied ruby source files from :" + $rubyplugindir + " # Copy-Item -Path $utilsplugindir -Destination $publishdir -Recurse -Force # Write-Host("successfully copied ruby util files from :" + $utilsplugindir + " to :" + $publishdir + " ") -ForegroundColor Green -Set-Location $currentdir \ No newline at end of file +Set-Location $currentdir diff --git a/source/plugins/go/src/utils.go b/source/plugins/go/src/utils.go index e5aa15bdd..6b3036f85 100644 --- a/source/plugins/go/src/utils.go +++ b/source/plugins/go/src/utils.go @@ -201,7 +201,6 @@ func CreateADXClient() { } } -// option 1 func ReadFileContents(fullPathToFileName string) (string, error) { return ReadFileContentsImpl(fullPathToFileName, ioutil.ReadFile) } diff --git a/source/plugins/ruby/CustomMetricsUtils.rb b/source/plugins/ruby/CustomMetricsUtils.rb index 14c3c8b72..fd9290b78 100644 --- a/source/plugins/ruby/CustomMetricsUtils.rb +++ b/source/plugins/ruby/CustomMetricsUtils.rb @@ -6,10 +6,10 @@ def initialize end class << self - def check_custom_metrics_availability(env=ENV) - aks_region = env['AKS_REGION'] - aks_resource_id = env['AKS_RESOURCE_ID'] - aks_cloud_environment = env['CLOUD_ENVIRONMENT'] + def check_custom_metrics_availability + aks_region = ENV['AKS_REGION'] + aks_resource_id = ENV['AKS_RESOURCE_ID'] + aks_cloud_environment = ENV['CLOUD_ENVIRONMENT'] if aks_region.to_s.empty? || aks_resource_id.to_s.empty? return false # This will also take care of AKS-Engine Scenario. AKS_REGION/AKS_RESOURCE_ID is not set for AKS-Engine. Only ACS_RESOURCE_NAME is set end diff --git a/source/plugins/ruby/MdmMetricsGenerator.rb b/source/plugins/ruby/MdmMetricsGenerator.rb index 2cf0e604e..0858990da 100644 --- a/source/plugins/ruby/MdmMetricsGenerator.rb +++ b/source/plugins/ruby/MdmMetricsGenerator.rb @@ -12,9 +12,9 @@ class MdmMetricsGenerator @os_type = ENV["OS_TYPE"] if !@os_type.nil? && !@os_type.empty? && @os_type.strip.casecmp("windows") == 0 - @log_path = Constants::WINDOWS_LOG_PATH + "mdm_metrics_generator.log" + @log_path = "/etc/omsagentwindows/mdm_metrics_generator.log" else - @log_path = Constants::LINUX_LOG_PATH + "mdm_metrics_generator.log" + @log_path = "/var/opt/microsoft/docker-cimprov/log/mdm_metrics_generator.log" end @log = Logger.new(@log_path, 1, 5000000) @@hostName = (OMS::Common.get_hostname) @@ -485,7 +485,7 @@ def is_numeric(o) true if Float(o) rescue false end - def getContainerResourceUtilizationThresholds(env=ENV) + def getContainerResourceUtilizationThresholds begin metric_threshold_hash = {} # Initilizing with default values @@ -495,32 +495,32 @@ def getContainerResourceUtilizationThresholds(env=ENV) metric_threshold_hash[Constants::PV_USED_BYTES] = Constants::DEFAULT_MDM_PV_UTILIZATION_THRESHOLD metric_threshold_hash[Constants::JOB_COMPLETION_TIME] = Constants::DEFAULT_MDM_JOB_COMPLETED_TIME_THRESHOLD_MINUTES - cpuThreshold = env["AZMON_ALERT_CONTAINER_CPU_THRESHOLD"] + cpuThreshold = ENV["AZMON_ALERT_CONTAINER_CPU_THRESHOLD"] if !cpuThreshold.nil? && !cpuThreshold.empty? #Rounding this to 2 decimal places, since this value is user configurable cpuThresholdFloat = (cpuThreshold.to_f).round(2) metric_threshold_hash[Constants::CPU_USAGE_NANO_CORES] = cpuThresholdFloat end - memoryRssThreshold = env["AZMON_ALERT_CONTAINER_MEMORY_RSS_THRESHOLD"] + memoryRssThreshold = ENV["AZMON_ALERT_CONTAINER_MEMORY_RSS_THRESHOLD"] if !memoryRssThreshold.nil? && !memoryRssThreshold.empty? memoryRssThresholdFloat = (memoryRssThreshold.to_f).round(2) metric_threshold_hash[Constants::MEMORY_RSS_BYTES] = memoryRssThresholdFloat end - memoryWorkingSetThreshold = env["AZMON_ALERT_CONTAINER_MEMORY_WORKING_SET_THRESHOLD"] + memoryWorkingSetThreshold = ENV["AZMON_ALERT_CONTAINER_MEMORY_WORKING_SET_THRESHOLD"] if !memoryWorkingSetThreshold.nil? && !memoryWorkingSetThreshold.empty? memoryWorkingSetThresholdFloat = (memoryWorkingSetThreshold.to_f).round(2) metric_threshold_hash[Constants::MEMORY_WORKING_SET_BYTES] = memoryWorkingSetThresholdFloat end - pvUsagePercentageThreshold = env["AZMON_ALERT_PV_USAGE_THRESHOLD"] + pvUsagePercentageThreshold = ENV["AZMON_ALERT_PV_USAGE_THRESHOLD"] if !pvUsagePercentageThreshold.nil? && !pvUsagePercentageThreshold.empty? pvUsagePercentageThresholdFloat = (pvUsagePercentageThreshold.to_f).round(2) metric_threshold_hash[Constants::PV_USED_BYTES] = pvUsagePercentageThresholdFloat end - jobCompletionTimeThreshold = env["AZMON_ALERT_JOB_COMPLETION_TIME_THRESHOLD"] + jobCompletionTimeThreshold = ENV["AZMON_ALERT_JOB_COMPLETION_TIME_THRESHOLD"] if !jobCompletionTimeThreshold.nil? && !jobCompletionTimeThreshold.empty? jobCompletionTimeThresholdInt = jobCompletionTimeThreshold.to_i metric_threshold_hash[Constants::JOB_COMPLETION_TIME] = jobCompletionTimeThresholdInt diff --git a/source/plugins/ruby/in_kube_nodes.rb b/source/plugins/ruby/in_kube_nodes.rb index 32ca499b1..35b5a6696 100644 --- a/source/plugins/ruby/in_kube_nodes.rb +++ b/source/plugins/ruby/in_kube_nodes.rb @@ -11,7 +11,7 @@ def initialize (kubernetesApiClient=nil, applicationInsightsUtility=nil, extensionUtils=nil, env=nil, - TELEMETRY_FLUSH_INTERVAL_IN_MINUTES=Constants::TELEMETRY_FLUSH_INTERVAL_IN_MINUTES) + telemetry_flush_interval=nil) super() require "yaml" @@ -30,6 +30,7 @@ def initialize (kubernetesApiClient=nil, @applicationInsightsUtility = applicationInsightsUtility == nil ? ApplicationInsightsUtility : applicationInsightsUtility @extensionUtils = extensionUtils == nil ? ExtensionUtils : extensionUtils @env = env == nil ? ENV : env + @TELEMETRY_FLUSH_INTERVAL_IN_MINUTES = telemetry_flush_interval == nil ? Constants::TELEMETRY_FLUSH_INTERVAL_IN_MINUTES : telemetry_flush_interval # these defines were previously at class scope Moving them into the constructor so that they can be set by unit tests @@configMapMountPath = "/etc/config/settings/log-data-collection-settings" @@ -64,9 +65,6 @@ def initialize (kubernetesApiClient=nil, require_relative "constants" @NodeCache = NodeStatsCache.new() - - # this is so that telemetry can be unit tested in a reasonable amount of time - @TELEMETRY_FLUSH_INTERVAL_IN_MINUTES = TELEMETRY_FLUSH_INTERVAL_IN_MINUTES end config_param :run_interval, :time, :default => 60 diff --git a/source/plugins/ruby/in_kube_nodes_test.rb b/source/plugins/ruby/in_kube_nodes_test.rb index fffaebf72..e3064011c 100644 --- a/source/plugins/ruby/in_kube_nodes_test.rb +++ b/source/plugins/ruby/in_kube_nodes_test.rb @@ -14,7 +14,7 @@ def setup Fluent::Test.setup end - def create_driver(conf = {}, kubernetesApiClient=nil, applicationInsightsUtility=nil, extensionUtils=nil, env=nil) + def create_driver(conf = {}, kubernetesApiClient=nil, applicationInsightsUtility=nil, extensionUtils=nil, env=nil, telemetry_flush_interval=nil) Fluent::Test::Driver::Input.new(Fluent::Plugin::Kube_nodeInventory_Input.new(kubernetesApiClient=kubernetesApiClient, applicationInsightsUtility=applicationInsightsUtility, extensionUtils=extensionUtils, @@ -129,7 +129,7 @@ def appInsightsUtil.sendMetricTelemetry(a, b, c) config = "run_interval 999999999" # only run once - d = create_driver(config, kubernetesApiClient=kubeApiClient, applicationInsightsUtility=appInsightsUtil, extensionUtils=extensionUtils, env=env, TELEMETRY_FLUSH_INTERVAL_IN_MINUTES=0) + d = create_driver(config, kubernetesApiClient=kubeApiClient, applicationInsightsUtility=appInsightsUtil, extensionUtils=extensionUtils, env=env, telemetry_flush_interval=0) d.instance.start d.instance.enumerate diff --git a/source/plugins/ruby/mdm_metrics_generator.log b/source/plugins/ruby/mdm_metrics_generator.log deleted file mode 100644 index d0d109899..000000000 --- a/source/plugins/ruby/mdm_metrics_generator.log +++ /dev/null @@ -1 +0,0 @@ -# Logfile created on 2021-08-04 17:54:56 -0700 by logger.rb/61378 diff --git a/test/unit-tests/canned-api-responses/get_nodes_response_2.json b/test/unit-tests/canned-api-responses/get_nodes_response_2.json deleted file mode 100644 index 1cc5ec151..000000000 --- a/test/unit-tests/canned-api-responses/get_nodes_response_2.json +++ /dev/null @@ -1 +0,0 @@ -{"kind":"NodeList","apiVersion":"v1","metadata":{"selfLink":"/api/v1/nodes","resourceVersion":"4597672"},"items":[{"metadata":{"name":"aks-nodepool1-24816391-vmss000000","selfLink":"/api/v1/nodes/aks-nodepool1-24816391-vmss000000","uid":"fe073f0a-e6bf-4d68-b4e5-ffaa42b91528","resourceVersion":"4597521","creationTimestamp":"2021-07-21T23:40:14Z","labels":{"agentpool":"nodepool1","beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/instance-type":"Standard_DS2_v2","beta.kubernetes.io/os":"linux","failure-domain.beta.kubernetes.io/region":"westus2","failure-domain.beta.kubernetes.io/zone":"0","kubernetes.azure.com/cluster":"MC_davidaks16_davidaks16_westus2","kubernetes.azure.com/mode":"system","kubernetes.azure.com/node-image-version":"AKSUbuntu-1804gen2containerd-2021.07.03","kubernetes.azure.com/os-sku":"Ubuntu","kubernetes.azure.com/role":"agent","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"aks-nodepool1-24816391-vmss000000","kubernetes.io/os":"linux","kubernetes.io/role":"agent","node-role.kubernetes.io/agent":"","node.kubernetes.io/instance-type":"Standard_DS2_v2","storageprofile":"managed","storagetier":"Premium_LRS","topology.kubernetes.io/region":"westus2","topology.kubernetes.io/zone":"0"},"annotations":{"node.alpha.kubernetes.io/ttl":"0","volumes.kubernetes.io/controller-managed-attach-detach":"true"},"managedFields":[{"manager":"kube-controller-manager","operation":"Update","apiVersion":"v1","time":"2021-07-21T23:40:20Z","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{"f:node.alpha.kubernetes.io/ttl":{}}}}},{"manager":"kubelet","operation":"Update","apiVersion":"v1","time":"2021-07-21T23:40:24Z","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:volumes.kubernetes.io/controller-managed-attach-detach":{}},"f:labels":{".":{},"f:agentpool":{},"f:beta.kubernetes.io/arch":{},"f:beta.kubernetes.io/instance-type":{},"f:beta.kubernetes.io/os":{},"f:failure-domain.beta.kubernetes.io/region":{},"f:failure-domain.beta.kubernetes.io/zone":{},"f:kubernetes.azure.com/cluster":{},"f:kubernetes.azure.com/mode":{},"f:kubernetes.azure.com/node-image-version":{},"f:kubernetes.azure.com/os-sku":{},"f:kubernetes.azure.com/role":{},"f:kubernetes.io/arch":{},"f:kubernetes.io/hostname":{},"f:kubernetes.io/os":{},"f:node.kubernetes.io/instance-type":{},"f:storageprofile":{},"f:storagetier":{},"f:topology.kubernetes.io/region":{},"f:topology.kubernetes.io/zone":{}}},"f:spec":{"f:providerID":{}},"f:status":{"f:addresses":{".":{},"k:{\"type\":\"Hostname\"}":{".":{},"f:address":{},"f:type":{}},"k:{\"type\":\"InternalIP\"}":{".":{},"f:address":{},"f:type":{}}},"f:allocatable":{".":{},"f:attachable-volumes-azure-disk":{},"f:cpu":{},"f:ephemeral-storage":{},"f:hugepages-1Gi":{},"f:hugepages-2Mi":{},"f:memory":{},"f:pods":{}},"f:capacity":{".":{},"f:attachable-volumes-azure-disk":{},"f:cpu":{},"f:ephemeral-storage":{},"f:hugepages-1Gi":{},"f:hugepages-2Mi":{},"f:memory":{},"f:pods":{}},"f:conditions":{".":{},"k:{\"type\":\"DiskPressure\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"MemoryPressure\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"PIDPressure\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Ready\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}},"f:config":{},"f:daemonEndpoints":{"f:kubeletEndpoint":{"f:Port":{}}},"f:images":{},"f:nodeInfo":{"f:architecture":{},"f:bootID":{},"f:containerRuntimeVersion":{},"f:kernelVersion":{},"f:kubeProxyVersion":{},"f:kubeletVersion":{},"f:machineID":{},"f:operatingSystem":{},"f:osImage":{},"f:systemUUID":{}}}}},{"manager":"kubectl-label","operation":"Update","apiVersion":"v1","time":"2021-07-21T23:40:53Z","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:labels":{"f:kubernetes.io/role":{},"f:node-role.kubernetes.io/agent":{}}}}},{"manager":"node-problem-detector","operation":"Update","apiVersion":"v1","time":"2021-08-10T18:10:02Z","fieldsType":"FieldsV1","fieldsV1":{"f:status":{"f:conditions":{"k:{\"type\":\"ContainerRuntimeProblem\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FilesystemCorruptionProblem\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FreezeScheduled\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FrequentContainerdRestart\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FrequentDockerRestart\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FrequentKubeletRestart\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FrequentUnregisterNetDevice\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"KernelDeadlock\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"KubeletProblem\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"PreemptScheduled\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"ReadonlyFilesystem\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"RebootScheduled\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"RedeployScheduled\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"TerminateScheduled\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}}}}}]},"spec":{"providerID":"azure:///subscriptions/3b875bf3-0eec-4d8c-bdee-25c7ccc1f130/resourceGroups/mc_davidaks16_davidaks16_westus2/providers/Microsoft.Compute/virtualMachineScaleSets/aks-nodepool1-24816391-vmss/virtualMachines/0"},"status":{"capacity":{"attachable-volumes-azure-disk":"8","cpu":"2","ephemeral-storage":"129900528Ki","hugepages-1Gi":"0","hugepages-2Mi":"0","memory":"7120616Ki","pods":"30"},"allocatable":{"attachable-volumes-azure-disk":"8","cpu":"1900m","ephemeral-storage":"119716326407","hugepages-1Gi":"0","hugepages-2Mi":"0","memory":"4675304Ki","pods":"30"},"conditions":[{"type":"FrequentContainerdRestart","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoFrequentContainerdRestart","message":"containerd is functioning properly"},{"type":"FreezeScheduled","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoFreezeScheduled","message":"VM has no scheduled Freeze event"},{"type":"FrequentDockerRestart","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoFrequentDockerRestart","message":"docker is functioning properly"},{"type":"FilesystemCorruptionProblem","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"FilesystemIsOK","message":"Filesystem is healthy"},{"type":"KernelDeadlock","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"KernelHasNoDeadlock","message":"kernel has no deadlock"},{"type":"TerminateScheduled","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoTerminateScheduled","message":"VM has no scheduled Terminate event"},{"type":"ReadonlyFilesystem","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"FilesystemIsNotReadOnly","message":"Filesystem is not read-only"},{"type":"FrequentUnregisterNetDevice","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoFrequentUnregisterNetDevice","message":"node is functioning properly"},{"type":"KubeletProblem","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"KubeletIsUp","message":"kubelet service is up"},{"type":"PreemptScheduled","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:11:11Z","reason":"NoPreemptScheduled","message":"VM has no scheduled Preempt event"},{"type":"RedeployScheduled","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoRedeployScheduled","message":"VM has no scheduled Redeploy event"},{"type":"ContainerRuntimeProblem","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"ContainerRuntimeIsUp","message":"container runtime service is up"},{"type":"FrequentKubeletRestart","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoFrequentKubeletRestart","message":"kubelet is functioning properly"},{"type":"RebootScheduled","status":"False","lastHeartbeatTime":"2021-08-11T02:57:20Z","lastTransitionTime":"2021-08-10T18:10:01Z","reason":"NoRebootScheduled","message":"VM has no scheduled Reboot event"},{"type":"MemoryPressure","status":"False","lastHeartbeatTime":"2021-08-11T02:58:37Z","lastTransitionTime":"2021-07-21T23:40:14Z","reason":"KubeletHasSufficientMemory","message":"kubelet has sufficient memory available"},{"type":"DiskPressure","status":"False","lastHeartbeatTime":"2021-08-11T02:58:37Z","lastTransitionTime":"2021-07-21T23:40:14Z","reason":"KubeletHasNoDiskPressure","message":"kubelet has no disk pressure"},{"type":"PIDPressure","status":"False","lastHeartbeatTime":"2021-08-11T02:58:37Z","lastTransitionTime":"2021-07-21T23:40:14Z","reason":"KubeletHasSufficientPID","message":"kubelet has sufficient PID available"},{"type":"Ready","status":"True","lastHeartbeatTime":"2021-08-11T02:58:37Z","lastTransitionTime":"2021-07-21T23:40:24Z","reason":"KubeletReady","message":"kubelet is posting ready status. AppArmor enabled"}],"addresses":[{"type":"Hostname","address":"aks-nodepool1-24816391-vmss000000"},{"type":"InternalIP","address":"10.240.0.4"}],"daemonEndpoints":{"kubeletEndpoint":{"Port":10250}},"nodeInfo":{"machineID":"17a654260e2c4a9bb3a3eb4b4188e4b4","systemUUID":"7ff599e4-909e-4950-a044-ff8613af3af9","bootID":"02bb865b-a469-43cd-8b0b-5ceb4ecd80b0","kernelVersion":"5.4.0-1051-azure","osImage":"Ubuntu 18.04.5 LTS","containerRuntimeVersion":"containerd://1.4.4+azure","kubeletVersion":"v1.19.11","kubeProxyVersion":"v1.19.11","operatingSystem":"linux","architecture":"amd64"},"images":[{"names":["mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021-1"],"sizeBytes":331689060},{"names":["mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod06112021"],"sizeBytes":330099815},{"names":["mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021-hotfix"],"sizeBytes":271471426},{"names":["mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod05202021"],"sizeBytes":269703297},{"names":["mcr.microsoft.com/azuremonitor/containerinsights/ciprod:ciprod03262021"],"sizeBytes":264732875},{"names":["mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.19.0"],"sizeBytes":166352383},{"names":["mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210623.2"],"sizeBytes":147750148},{"names":["mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210524.1"],"sizeBytes":146446618},{"names":["mcr.microsoft.com/aks/hcp/hcp-tunnel-front:master.210427.1"],"sizeBytes":136242776},{"names":["mcr.microsoft.com/oss/calico/node:v3.8.9.5"],"sizeBytes":101794833},{"names":["mcr.microsoft.com/oss/kubernetes/ingress/nginx-ingress-controller:0.47.0"],"sizeBytes":101445696},{"names":["mcr.microsoft.com/oss/kubernetes/autoscaler/cluster-proportional-autoscaler:1.3.0_v0.0.5"],"sizeBytes":101194562},{"names":["mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210623.2"],"sizeBytes":96125176},{"names":["mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210524.1"],"sizeBytes":95879501},{"names":["mcr.microsoft.com/oss/kubernetes/exechealthz:1.2_v0.0.5"],"sizeBytes":94348102},{"names":["mcr.microsoft.com/oss/calico/node:v3.8.9.2"],"sizeBytes":93537927},{"names":["mcr.microsoft.com/aks/acc/sgx-attestation:2.0"],"sizeBytes":91841669},{"names":["mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.4.0"],"sizeBytes":91324193},{"names":["mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi:v1.2.0"],"sizeBytes":89103171},{"names":["mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.0.1-rc3"],"sizeBytes":86839805},{"names":["mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.2.0"],"sizeBytes":86488586},{"names":["mcr.microsoft.com/aks/hcp/tunnel-openvpn:master.210427.1"],"sizeBytes":86120048},{"names":["mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.3.0"],"sizeBytes":81252495},{"names":["mcr.microsoft.com/azure-application-gateway/kubernetes-ingress:1.4.0"],"sizeBytes":79586703},{"names":["mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.4.0"],"sizeBytes":78795016},{"names":["mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi:v1.2.0"],"sizeBytes":76527179},{"names":["mcr.microsoft.com/containernetworking/azure-npm:v1.1.8"],"sizeBytes":75025803},{"names":["mcr.microsoft.com/containernetworking/azure-npm:v1.2.2_hotfix"],"sizeBytes":73533889},{"names":["mcr.microsoft.com/containernetworking/azure-npm:v1.3.1"],"sizeBytes":72242894},{"names":["mcr.microsoft.com/containernetworking/azure-npm:v1.2.8"],"sizeBytes":70622822},{"names":["mcr.microsoft.com/oss/nvidia/k8s-device-plugin:v0.9.0"],"sizeBytes":67291599},{"names":["mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.1"],"sizeBytes":66415836},{"names":["mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc7"],"sizeBytes":65965658},{"names":["mcr.microsoft.com/containernetworking/azure-npm:v1.2.1"],"sizeBytes":64123775},{"names":["mcr.microsoft.com/oss/calico/cni:v3.8.9.3"],"sizeBytes":63581323},{"names":["mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8"],"sizeBytes":63154716},{"names":["mcr.microsoft.com/oss/calico/cni:v3.8.9.2"],"sizeBytes":61626312},{"names":["mcr.microsoft.com/oss/calico/node:v3.18.1"],"sizeBytes":60500885},{"names":["mcr.microsoft.com/oss/calico/node:v3.17.2"],"sizeBytes":58419768},{"names":["mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8_hotfix","mcr.microsoft.com/containernetworking/networkmonitor:v1.1.8post2"],"sizeBytes":56368756},{"names":["mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:282543237a1aa3f407656290f454b7068a92e1abe2156082c750d5abfbcad90c","mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.2"],"sizeBytes":56310724},{"names":["mcr.microsoft.com/oss/calico/node:v3.19.0"],"sizeBytes":55228749},{"names":["mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526.1"],"sizeBytes":54692048},{"names":["mcr.microsoft.com/oss/kubernetes/dashboard:v2.0.0-rc3"],"sizeBytes":50803639},{"names":["mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.19"],"sizeBytes":49759361},{"names":["mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.5"],"sizeBytes":49704644},{"names":["mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver:v0.0.21"],"sizeBytes":49372390},{"names":["mcr.microsoft.com/oss/kubernetes/kube-proxy@sha256:a64d3538b72905b07356881314755b02db3675ff47ee2bcc49dd7be856e285d5","mcr.microsoft.com/oss/kubernetes/kube-proxy:v1.19.11-hotfix.20210526"],"sizeBytes":49322942},{"names":["mcr.microsoft.com/oss/azure/aad-pod-identity/nmi:v1.7.4"],"sizeBytes":48108311},{"names":["mcr.microsoft.com/oss/kubernetes/kubernetes-dashboard:v1.10.1"],"sizeBytes":44907744}],"config":{}}}]} \ No newline at end of file diff --git a/test/unit-tests/run_go_tests.sh b/test/unit-tests/run_go_tests.sh index 22ab29069..7036531fd 100755 --- a/test/unit-tests/run_go_tests.sh +++ b/test/unit-tests/run_go_tests.sh @@ -3,7 +3,10 @@ set -e OLD_PATH=$(pwd) SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" cd $SCRIPTPATH/../../source/plugins/go/src +echo "# Runnign go generate" go generate + +echo "# Running go test ." go test . cd $OLD_PATH diff --git a/test/unit-tests/run_ruby_tests.sh b/test/unit-tests/run_ruby_tests.sh index 103704d4a..824346eee 100755 --- a/test/unit-tests/run_ruby_tests.sh +++ b/test/unit-tests/run_ruby_tests.sh @@ -7,6 +7,7 @@ set -e OLD_PATH=$(pwd) SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" # cd $SCRIPTPATH/../../source/plugins/ruby +echo "# Running ruby $SCRIPTPATH/test_driver.rb $1 $2" ruby $SCRIPTPATH/test_driver.rb $1 $2 cd $OLD_PATH From eef9fcca5244263efad3cfd84c8300981202bfc8 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Mon, 23 Aug 2021 14:39:54 -0700 Subject: [PATCH 28/33] ready for review --- build/windows/Makefile.ps1 | 5 ----- source/plugins/ruby/in_kube_nodes.rb | 7 ++----- source/plugins/ruby/in_kube_nodes_test.rb | 11 +++++++---- test/unit-tests/test_driver.rb | 1 - 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/build/windows/Makefile.ps1 b/build/windows/Makefile.ps1 index e397a2315..d0d8ab0fb 100644 --- a/build/windows/Makefile.ps1 +++ b/build/windows/Makefile.ps1 @@ -185,9 +185,4 @@ Write-Host("copying ruby source files from :" + $rubyplugindir + " to :" + $pu Copy-Item -Path $rubyplugindir -Destination $publishdir -Recurse -Force Write-Host("successfully copied ruby source files from :" + $rubyplugindir + " to :" + $publishdir + " ") -ForegroundColor Green -# $utilsplugindir = Join-Path -Path $rootdir -ChildPath "source\plugins\utils" -# Write-Host("copying ruby util files from :" + $utilsplugindir + " to :" + $publishdir + " ...") -# Copy-Item -Path $utilsplugindir -Destination $publishdir -Recurse -Force -# Write-Host("successfully copied ruby util files from :" + $utilsplugindir + " to :" + $publishdir + " ") -ForegroundColor Green - Set-Location $currentdir diff --git a/source/plugins/ruby/in_kube_nodes.rb b/source/plugins/ruby/in_kube_nodes.rb index 35b5a6696..a32a32769 100644 --- a/source/plugins/ruby/in_kube_nodes.rb +++ b/source/plugins/ruby/in_kube_nodes.rb @@ -21,9 +21,8 @@ def initialize (kubernetesApiClient=nil, require_relative "KubernetesApiClient" require_relative "ApplicationInsightsUtility" - # TODO: oms_common and omslog appear to be unused. Remove them if they are - # require_relative "oms_common" - # require_relative "omslog" + require_relative "oms_common" + require_relative "omslog" require_relative "extension_utils" @kubernetesApiClient = kubernetesApiClient == nil ? KubernetesApiClient : kubernetesApiClient @@ -573,8 +572,6 @@ def getNodeTelemetryProps(item) return properties end end # Kube_Node_Input - - class NodeStatsCache # inner class for caching implementation (CPU and memory caching is handled the exact same way, so logic to do so is moved to a private inner class) # (to reduce code duplication) diff --git a/source/plugins/ruby/in_kube_nodes_test.rb b/source/plugins/ruby/in_kube_nodes_test.rb index e3064011c..248d697dc 100644 --- a/source/plugins/ruby/in_kube_nodes_test.rb +++ b/source/plugins/ruby/in_kube_nodes_test.rb @@ -21,6 +21,7 @@ def create_driver(conf = {}, kubernetesApiClient=nil, applicationInsightsUtility env=env)).configure(conf) end + # Collection time of scrapped data will always be different. Overwrite it in any records returned by in_kube_ndes.rb def overwrite_collection_time(data) if data.key?("CollectionTime") data["CollectionTime"] = "~CollectionTime~" @@ -69,13 +70,12 @@ def extensionUtils.isAADMSIAuthMode ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"cpuCapacityNanoCores\",\"Value\":2000000000.0}]"})] => true, ["oneagent.containerInsights.LINUX_PERF_BLOB", overwrite_collection_time({"Timestamp"=>"2021-08-17T20:24:18Z", "Host"=>"aks-nodepool1-24816391-vmss000000", "Computer"=>"aks-nodepool1-24816391-vmss000000", "ObjectName"=>"K8SNode", "InstanceName"=>"None/aks-nodepool1-24816391-vmss000000", "json_Collections"=>"[{\"CounterName\":\"memoryCapacityBytes\",\"Value\":7291510784.0}]"})] => true} - #TODO: remove records from expected_responses as they are recieved (to make sure that they are all recieved exactly once) d.events.each do |tag, time, record| cleaned_record = overwrite_collection_time record if expected_responses.key?([tag, cleaned_record]) expected_responses[[tag, cleaned_record]] = true else - assert_equal(true, false) + assert(false, "got unexpected record") end end @@ -83,12 +83,14 @@ def extensionUtils.isAADMSIAuthMode assert(val, "expected record not emitted: #{key}") end + # make sure all mocked methods were called the expected number of times kubeApiClient.verify appInsightsUtil.verify extensionUtils.verify end - + # Sometimes customer tooling creates invalid node specs in the Kube API server (its happened more than once). + # This test makes sure that it doesn't creash the entire input plugin and other nodes are still collected def test_malformed_node_spec kubeApiClient = Minitest::Mock.new appInsightsUtil = Minitest::Mock.new @@ -109,7 +111,7 @@ def extensionUtils.isAADMSIAuthMode # Set up the KubernetesApiClient Mock. Note: most of the functions in KubernetesApiClient are pure (access no # state other than their arguments), so there is no need to mock them (this test file would be far longer and # more brittle). Instead, in_kube_nodes bypasses the mock and directly calls these functions in KubernetesApiClient. - # Ideally the pure functions in KubernetesApiClient would be refactored into their own file. + # Ideally the pure functions in KubernetesApiClient would be refactored into their own file to reduce confusion. nodes_api_response = eval(File.open("test/unit-tests/canned-api-responses/kube-nodes-malformed.txt").read) kubeApiClient.expect(:getResourcesAndContinuationToken, [nil, nodes_api_response], ["nodes?limit=200"]) kubeApiClient.expect(:getClusterName, "/cluster-name") @@ -144,6 +146,7 @@ def appInsightsUtil.sendMetricTelemetry(a, b, c) ["oneagent.containerInsights.LINUX_PERF_BLOB", {"Timestamp"=>"~Timestamp~", "Host"=>"correct-node", "Computer"=>"correct-node", "ObjectName"=>"K8SNode", "InstanceName"=>"None/correct-node", "json_Collections"=>"[{\"CounterName\":\"cpuCapacityNanoCores\",\"Value\":2000000.0}]"}] => false, ["oneagent.containerInsights.LINUX_PERF_BLOB", {"Timestamp"=>"~Timestamp~", "Host"=>"correct-node", "Computer"=>"correct-node", "ObjectName"=>"K8SNode", "InstanceName"=>"None/correct-node", "json_Collections"=>"[{\"CounterName\":\"memoryCapacityBytes\",\"Value\":555.0}]"}] => false, + # these records are for the malformed node (it doesn't have limits or requests set so there are no PERF records) ["oneagent.containerInsights.KUBE_NODE_INVENTORY_BLOB", {"CollectionTime"=>"~CollectionTime~", "Computer"=>"malformed-node", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"malformed-node", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"}] => false, ["mdm.kubenodeinventory", {"CollectionTime"=>"~CollectionTime~", "Computer"=>"malformed-node", "ClusterName"=>"/cluster-name", "ClusterId"=>"/cluster-id", "CreationTimeStamp"=>"2021-07-21T23:40:14Z", "Labels"=>[{"agentpool"=>"nodepool1", "beta.kubernetes.io/arch"=>"amd64", "beta.kubernetes.io/instance-type"=>"Standard_DS2_v2", "beta.kubernetes.io/os"=>"linux", "failure-domain.beta.kubernetes.io/region"=>"westus2", "failure-domain.beta.kubernetes.io/zone"=>"0", "kubernetes.azure.com/cluster"=>"MC_davidaks16_davidaks16_westus2", "kubernetes.azure.com/mode"=>"system", "kubernetes.azure.com/node-image-version"=>"AKSUbuntu-1804gen2containerd-2021.07.03", "kubernetes.azure.com/os-sku"=>"Ubuntu", "kubernetes.azure.com/role"=>"agent", "kubernetes.io/arch"=>"amd64", "kubernetes.io/hostname"=>"malformed-node", "kubernetes.io/os"=>"linux", "kubernetes.io/role"=>"agent", "node-role.kubernetes.io/agent"=>"", "node.kubernetes.io/instance-type"=>"Standard_DS2_v2", "storageprofile"=>"managed", "storagetier"=>"Premium_LRS", "topology.kubernetes.io/region"=>"westus2", "topology.kubernetes.io/zone"=>"0"}], "Status"=>"Ready", "KubernetesProviderID"=>"azure", "LastTransitionTimeReady"=>"2021-07-21T23:40:24Z", "KubeletVersion"=>"v1.19.11", "KubeProxyVersion"=>"v1.19.11"}] => false, ["oneagent.containerInsights.CONTAINER_NODE_INVENTORY_BLOB", {"CollectionTime"=>"~CollectionTime~", "Computer"=>"malformed-node", "OperatingSystem"=>"Ubuntu 18.04.5 LTS", "DockerVersion"=>"containerd://1.4.4+azure"}] => false diff --git a/test/unit-tests/test_driver.rb b/test/unit-tests/test_driver.rb index f4593748d..32687cc99 100644 --- a/test/unit-tests/test_driver.rb +++ b/test/unit-tests/test_driver.rb @@ -1,4 +1,3 @@ -# TODO: can we get rid of this global flag? $in_unit_test = true script_path = __dir__ From 504bcf521c5b428007181ca877eace52bce576c2 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Mon, 23 Aug 2021 14:52:03 -0700 Subject: [PATCH 29/33] installing fluentd in github action container (not sure why that wasn't needed earlier) --- .github/workflows/run_unit_tests.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index f81e3678d..f9c7759fd 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -20,6 +20,10 @@ jobs: steps: - name: Check out repository code uses: actions/checkout@v2 + - name: install fluent + run: | + gem install fluentd -v "1.12.2" --no-document + fluentd --setup ./fluent - name: Run unit tests run: | cd ${{ github.workspace }} From e367370f8ed21065bc6945de569b30e2832e09f4 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Mon, 23 Aug 2021 15:23:19 -0700 Subject: [PATCH 30/33] fixing github actions again --- .github/workflows/run_unit_tests.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index f9c7759fd..87692a837 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -22,8 +22,9 @@ jobs: uses: actions/checkout@v2 - name: install fluent run: | - gem install fluentd -v "1.12.2" --no-document - fluentd --setup ./fluent + whoami + sudo gem install fluentd -v "1.12.2" --no-document + sudo fluentd --setup ./fluent - name: Run unit tests run: | cd ${{ github.workspace }} From 9118de6519236aacb6f3af4b0b9ecd22568ecd32 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Mon, 23 Aug 2021 15:25:38 -0700 Subject: [PATCH 31/33] removing byebug --- .github/workflows/run_unit_tests.yml | 1 - source/plugins/ruby/in_kube_nodes_test.rb | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index 87692a837..29f5afc7a 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -22,7 +22,6 @@ jobs: uses: actions/checkout@v2 - name: install fluent run: | - whoami sudo gem install fluentd -v "1.12.2" --no-document sudo fluentd --setup ./fluent - name: Run unit tests diff --git a/source/plugins/ruby/in_kube_nodes_test.rb b/source/plugins/ruby/in_kube_nodes_test.rb index 248d697dc..8f4984c6c 100644 --- a/source/plugins/ruby/in_kube_nodes_test.rb +++ b/source/plugins/ruby/in_kube_nodes_test.rb @@ -5,7 +5,6 @@ require 'fluent/test/helpers' require_relative 'in_kube_nodes.rb' -require 'byebug' class InKubeNodesTests < Minitest::Test include Fluent::Test::Helpers From c5d5221510e93930c2ce509f33d81cc5edb900c7 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Tue, 24 Aug 2021 12:17:50 -0700 Subject: [PATCH 32/33] fixing windows build --- kubernetes/windows/Dockerfile | 1 - kubernetes/windows/Dockerfile-dev-image | 1 - 2 files changed, 2 deletions(-) diff --git a/kubernetes/windows/Dockerfile b/kubernetes/windows/Dockerfile index 0ba64cd75..290deef40 100644 --- a/kubernetes/windows/Dockerfile +++ b/kubernetes/windows/Dockerfile @@ -71,7 +71,6 @@ COPY ./omsagentwindows/installer/scripts/rubyKeepCertificateAlive/*.rb /etc/flue #Copy fluentd ruby plugins COPY ./omsagentwindows/ruby/ /etc/fluent/plugin/ -COPY ./omsagentwindows/utils/*.rb /etc/fluent/plugin/ ENV AGENT_VERSION ${IMAGE_TAG} ENV OS_TYPE "windows" diff --git a/kubernetes/windows/Dockerfile-dev-image b/kubernetes/windows/Dockerfile-dev-image index 6764ef8c4..35aa83bd9 100644 --- a/kubernetes/windows/Dockerfile-dev-image +++ b/kubernetes/windows/Dockerfile-dev-image @@ -33,7 +33,6 @@ COPY ./omsagentwindows/installer/scripts/rubyKeepCertificateAlive/*.rb /etc/flue #Copy fluentd ruby plugins COPY ./omsagentwindows/ruby/ /etc/fluent/plugin/ -COPY ./omsagentwindows/utils/*.rb /etc/fluent/plugin/ ENV AGENT_VERSION ${IMAGE_TAG} ENV OS_TYPE "windows" From 66f89a6a43046b5fc48261b0cd04ce285e0e76c5 Mon Sep 17 00:00:00 2001 From: David Michelman Date: Thu, 26 Aug 2021 23:14:08 -0700 Subject: [PATCH 33/33] updating windows makefile.ps1 --- build/windows/Makefile.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/build/windows/Makefile.ps1 b/build/windows/Makefile.ps1 index d0d8ab0fb..b9bd1f3e4 100644 --- a/build/windows/Makefile.ps1 +++ b/build/windows/Makefile.ps1 @@ -183,6 +183,7 @@ Write-Host("successfully copied installer files conf and scripts from :" + $inst $rubyplugindir = Join-Path -Path $rootdir -ChildPath "source\plugins\ruby" Write-Host("copying ruby source files from :" + $rubyplugindir + " to :" + $publishdir + " ...") Copy-Item -Path $rubyplugindir -Destination $publishdir -Recurse -Force +Get-ChildItem $Path | Where{$_.Name -Match ".*_test\.rb"} | Remove-Item Write-Host("successfully copied ruby source files from :" + $rubyplugindir + " to :" + $publishdir + " ") -ForegroundColor Green Set-Location $currentdir