├── .devcontainer ├── devcontainer.json └── installMoreTools.sh ├── .gitattributes ├── .github ├── .markdownlint.json ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yaml ├── pull_request_template.md └── workflows │ ├── codeql.yaml │ ├── commit-message.yaml │ ├── daily-scale-test.yaml │ ├── docs.yaml │ ├── e2e.yaml │ ├── golangci-lint.yaml │ ├── goreleaser.yaml │ ├── images.yaml │ ├── kapinger.yaml │ ├── markdownlint.yaml │ ├── perf-manual.yaml │ ├── perf-schedule.yaml │ ├── perf-template.yaml │ ├── release-charts.yaml │ ├── release-images.yaml │ ├── release-validation.yaml │ ├── scale-test.yaml │ ├── stale.yaml │ ├── test-multicloud.yml │ ├── test.yaml │ ├── trivy.yaml │ └── update-hubble.yaml ├── .gitignore ├── .golangci.yaml ├── .goreleaser.yaml ├── .krew.yaml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── NOTICE.txt ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── captureworkload ├── README.md └── main.go ├── cli ├── Dockerfile ├── README.md ├── cmd │ ├── capture │ │ ├── capture.go │ │ ├── create.go │ │ ├── delete.go │ │ ├── download.go │ │ ├── list.go │ │ └── table_util.go │ ├── config.go │ ├── root.go │ ├── shell.go │ ├── trace.go │ └── version.go ├── cmd_test.go └── main.go ├── cmd ├── hubble │ ├── LICENSE │ ├── cells_linux.go │ ├── daemon_linux.go │ └── daemon_main_linux.go ├── hubble_linux.go ├── root.go └── standard │ ├── daemon.go │ ├── daemon_linux.go │ └── daemon_windows.go ├── controller ├── Dockerfile ├── Dockerfile.gogen ├── Dockerfile.proto ├── Dockerfile.windows-2019 ├── Dockerfile.windows-2022 ├── Dockerfile.windows-cgo ├── Dockerfile.windows-native ├── Dockerfile.windows-native.dockerignore └── main.go ├── crd ├── Makefile ├── README.md └── api │ └── v1alpha1 │ ├── capture_types.go │ ├── groupversion_info.go │ ├── metricsconfiguration_types.go │ ├── retinaendpoint_types.go │ ├── tracesconfiguration_types.go │ ├── validations │ ├── validate_metricconfiguration.go │ ├── validate_metricconfiguration_test.go │ ├── validate_traceconfiguration.go │ └── validate_traceconfiguration_test.go │ └── zz_generated.deepcopy.go ├── deploy ├── grafana-dashboards │ ├── clusters.json │ ├── hubble-dns.json │ ├── hubble-pod-flows-namespace.json │ ├── hubble-pod-flows-workload.json │ ├── standard-dns.json │ └── standard-pod-level.json ├── hubble │ ├── manifests │ │ └── controller │ │ │ └── helm │ │ │ └── retina │ │ │ ├── .helmignore │ │ │ ├── Chart.yaml │ │ │ ├── templates │ │ │ ├── _helpers.tpl │ │ │ ├── agent │ │ │ │ ├── clusterrole.yaml │ │ │ │ ├── clusterrolebinding.yaml │ │ │ │ ├── configmap.yaml │ │ │ │ ├── daemonset.yaml │ │ │ │ ├── service.yaml │ │ │ │ └── serviceaccount.yaml │ │ │ ├── hubble-relay │ │ │ │ ├── configmap.yaml │ │ │ │ ├── deployment.yaml │ │ │ │ ├── metrics-service.yaml │ │ │ │ ├── poddisruptionbudget.yaml │ │ │ │ ├── service.yaml │ │ │ │ ├── serviceaccount.yaml │ │ │ │ └── servicemonitor.yaml │ │ │ ├── hubble-ui │ │ │ │ ├── _nginx.tpl │ │ │ │ ├── clusterrole.yaml │ │ │ │ ├── clusterrolebinding.yaml │ │ │ │ ├── configmap.yaml │ │ │ │ ├── deployment.yaml │ │ │ │ ├── ingress.yaml │ │ │ │ ├── poddisruptionbudget.yaml │ │ │ │ ├── service.yaml │ │ │ │ └── serviceaccount.yaml │ │ │ ├── hubble │ │ │ │ ├── dashboards-configmap.yaml │ │ │ │ ├── metrics-service.yaml │ │ │ │ ├── peer-service.yaml │ │ │ │ ├── servicemonitor.yaml │ │ │ │ ├── tls-certmanager │ │ │ │ │ ├── relay-client-secret.yaml │ │ │ │ │ ├── relay-server-secret.yaml │ │ │ │ │ ├── server-secret.yaml │ │ │ │ │ └── ui-client-certs.yaml │ │ │ │ ├── tls-cronjob │ │ │ │ │ ├── _job-spec.tpl │ │ │ │ │ ├── clusterrole.yaml │ │ │ │ │ ├── cronjob.yaml │ │ │ │ │ ├── job.yaml │ │ │ │ │ ├── rolebinding.yaml │ │ │ │ │ └── serviceaccount.yaml │ │ │ │ ├── tls-helm │ │ │ │ │ ├── _helpers.tpl │ │ │ │ │ ├── relay-client-secret.yaml │ │ │ │ │ ├── relay-server-secret.yaml │ │ │ │ │ ├── server-secret.yaml │ │ │ │ │ └── ui-client-certs.yaml │ │ │ │ └── tls-provided │ │ │ │ │ ├── relay-client-secret.yaml │ │ │ │ │ ├── relay-server-secret.yaml │ │ │ │ │ ├── server-secret.yaml │ │ │ │ │ └── ui-client-certs.yaml │ │ │ ├── operator │ │ │ │ ├── clusterrole.yaml │ │ │ │ ├── clusterrolebinding.yaml │ │ │ │ ├── configmap.yaml │ │ │ │ ├── deployment.yaml │ │ │ │ └── serviceaccount.yaml │ │ │ └── validate.yaml │ │ │ └── values.yaml │ └── prometheus │ │ └── values.yaml ├── standard │ ├── manifests │ │ └── controller │ │ │ └── helm │ │ │ └── retina │ │ │ ├── .helmignore │ │ │ ├── Chart.yaml │ │ │ ├── crds │ │ │ ├── retina.sh_captures.yaml │ │ │ ├── retina.sh_metricsconfigurations.yaml │ │ │ ├── retina.sh_retinaendpoints.yaml │ │ │ └── retina.sh_tracesconfigurations.yaml │ │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── configmap.yaml │ │ │ ├── daemonset.yaml │ │ │ ├── networkobserver.yaml │ │ │ ├── operator.yaml │ │ │ ├── podmonitor.yaml │ │ │ ├── rbac.yaml │ │ │ ├── service.yaml │ │ │ ├── serviceaccount.yaml │ │ │ ├── servicemonitor.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ │ └── values.yaml │ ├── prometheus │ │ ├── ama-metrics-settings-configmap.yaml │ │ ├── collector-config-template.yml │ │ ├── deploy-retina-clusters.sh │ │ ├── network-observability │ │ │ ├── create-cm.sh │ │ │ ├── network-observability-svc.yaml │ │ │ └── prometheus-config │ │ ├── retina-windows │ │ │ ├── create-cm.sh │ │ │ └── prometheus-config │ │ ├── retina │ │ │ ├── create-cm.sh │ │ │ └── prometheus-config │ │ └── values.yaml │ ├── registercrd.go │ └── registercrd_test.go └── testutils │ └── grafana │ └── dashboards │ ├── simplify-grafana-overwrite_test.go │ ├── simplify-grafana.go │ └── simplify-grafana_test.go ├── docs ├── 01-Introduction │ ├── 01-intro.md │ ├── 02-architecture.md │ └── img │ │ ├── Retina Arch.excalidraw │ │ ├── Retina Arch.png │ │ ├── control-plane.excalidraw │ │ ├── control-plane.png │ │ ├── data-plane.excalidraw │ │ ├── data-plane.png │ │ ├── hubble-control-plane.excalidraw │ │ ├── hubble-control-plane.png │ │ └── retina-components.png ├── 02-Installation │ ├── 01-Setup.md │ ├── 02-CLI.md │ ├── 03-Config.md │ ├── 04-prometheus.md │ ├── 05-grafana.md │ └── img │ │ ├── grafana-datasources.png │ │ ├── grafana-import.png │ │ ├── grafana-kubernetes-networking-dash.png │ │ ├── grafana-login.png │ │ ├── grafana-retina-dns-dash.png │ │ └── prometheus-retina-targets.png ├── 03-Metrics │ ├── 01-metrics-intro.md │ ├── 02-hubble_metrics.md │ ├── annotations.md │ ├── configuration.md │ ├── modes │ │ ├── advanced.md │ │ ├── basic.md │ │ └── modes.md │ └── plugins │ │ ├── Linux │ │ ├── ciliumeventobserver.md │ │ ├── dns.md │ │ ├── dropreason.md │ │ ├── infiniband.md │ │ ├── linuxutil.md │ │ ├── packetforward.md │ │ ├── packetparser.md │ │ └── tcpretrans.md │ │ ├── Windows │ │ └── hnsstats.md │ │ └── readme.md ├── 04-Captures │ ├── 01-overview.md │ ├── 02-cli.md │ ├── 03-crd.md │ ├── 04-managed-storage-account.md │ └── img │ │ ├── capture-architecture-with-operator.png │ │ ├── capture-architecture-without-operator.png │ │ ├── capture-managed-storage-account.png │ │ └── retina-release.png ├── 05-Concepts │ ├── CRDs │ │ ├── Capture.md │ │ ├── MetricsConfiguration.md │ │ └── RetinaEndpoint.md │ └── data-aggregation.md ├── 06-Troubleshooting │ ├── basic-metrics.md │ ├── capture.md │ ├── imgs │ │ ├── prom-retina-config.png │ │ ├── prom-retina-service-discovery1.png │ │ ├── prom-retina-service-discovery2.png │ │ └── prometheus-retina-targets.png │ └── shell.md ├── 07-Integrations │ ├── 01-hubble-cli.md │ ├── 02-hubble-ui.md │ ├── 03-vscode.md │ ├── 04-wireshark.md │ └── img │ │ ├── hubble-cli.png │ │ ├── hubble-ui-home.png │ │ ├── hubble-ui-service-map.png │ │ └── wireshark.png └── 08-Contributing │ ├── 01-overview.md │ └── 02-development.md ├── get-certs.sh ├── go.mod ├── go.sum ├── hack └── tools │ ├── kapinger │ ├── .dockerignore │ ├── Dockerfile │ ├── clients │ │ ├── client.go │ │ ├── dns.go │ │ └── http.go │ ├── config │ │ └── config.go │ ├── go.mod │ ├── go.sum │ ├── main.go │ └── servers │ │ ├── http.go │ │ ├── server.go │ │ ├── tcp.go │ │ ├── udp.go │ │ └── util.go │ └── toolbox │ ├── .dockerignore │ ├── Dockerfile │ ├── go.mod │ ├── go.sum │ └── main.go ├── init └── retina │ └── main_linux.go ├── internal ├── buildinfo │ └── buildinfo.go └── ktime │ ├── ktime.go │ ├── ktime_other.go │ └── ktime_unix.go ├── operator ├── Dockerfile ├── Dockerfile.windows-2019 ├── Dockerfile.windows-2022 ├── cache │ └── types.go ├── cilium-crds │ ├── config │ │ └── config_linux.go │ └── k8s │ │ ├── LICENSE │ │ ├── apis │ │ ├── cell.go │ │ └── register.go │ │ ├── fakeresource.go │ │ ├── resource_ctors.go │ │ └── resources.go ├── cmd │ ├── cilium-crds │ │ ├── LICENSE │ │ ├── cells_linux.go │ │ ├── flags.go │ │ ├── flags_provider.go │ │ ├── lifecycle.go │ │ ├── metrics.go │ │ ├── root_linux.go │ │ └── zap_linux.go │ ├── cilium_crds_cmd_linux.go │ ├── root.go │ └── standard │ │ └── deployment.go ├── config │ ├── config.go │ ├── config_test.go │ └── testwith │ │ ├── config-small-telemetry-interval.yaml │ │ ├── config-without-telemetry-interval.yaml │ │ └── config.yaml └── main.go ├── pkg ├── api │ └── trace.yml ├── bpf │ └── setup_linux.go ├── capture │ ├── capture_manager.go │ ├── capture_manager_test.go │ ├── constants │ │ ├── job_env.go │ │ ├── job_specification.go │ │ └── windows.go │ ├── crd_to_job.go │ ├── crd_to_job_test.go │ ├── doc.go │ ├── error.go │ ├── file │ │ ├── capture_filename.go │ │ └── timestamp.go │ ├── outputlocation │ │ ├── blob.go │ │ ├── blob_test.go │ │ ├── hostpath.go │ │ ├── managed │ │ │ ├── doc.go │ │ │ └── storageaccount.go │ │ ├── output.go │ │ ├── output_test.go │ │ ├── pvc.go │ │ └── s3.go │ ├── provider │ │ ├── interface.go │ │ ├── mock_network_capture.go │ │ ├── network_capture_common.go │ │ ├── network_capture_test.go │ │ ├── network_capture_unix.go │ │ └── network_capture_win.go │ ├── test_helper.go │ └── utils │ │ ├── capture_image.go │ │ ├── capture_image_test.go │ │ ├── label.go │ │ └── label_test.go ├── client │ └── client.go ├── common │ ├── apiretry │ │ └── apiretry.go │ ├── baseobject.go │ ├── dirtycache.go │ ├── dirtycache_test.go │ ├── endpoint.go │ ├── ipaddr.go │ ├── node.go │ ├── pubsubtopics.go │ ├── service.go │ ├── types.go │ └── types_test.go ├── config │ ├── capture.go │ ├── config.go │ ├── config_test.go │ ├── hubble_config_linux.go │ └── testwith │ │ ├── config-mock.yaml │ │ ├── config-small-telemetry-interval.yaml │ │ ├── config-win.yaml │ │ ├── config-without-telemetry-interval.yaml │ │ └── config.yaml ├── controllers │ ├── cache │ │ ├── cache.go │ │ ├── cache_test.go │ │ ├── mock_cacheinterface.go │ │ └── types.go │ ├── daemon │ │ ├── metricsconfiguration │ │ │ ├── metricsconfiguration_controller.go │ │ │ └── metricsconfiguration_controller_test.go │ │ ├── namespace │ │ │ ├── namespace_controller.go │ │ │ └── namespace_controller_test.go │ │ ├── node │ │ │ └── controller.go │ │ ├── nodereconciler │ │ │ ├── cell_linux.go │ │ │ └── node_controller_linux.go │ │ ├── pod │ │ │ └── controller.go │ │ ├── retinaendpoint │ │ │ ├── controller.go │ │ │ ├── controller_test.go │ │ │ └── suite_test.go │ │ └── service │ │ │ ├── controller.go │ │ │ └── controller_test.go │ └── operator │ │ ├── capture │ │ ├── controller.go │ │ ├── controller_test.go │ │ ├── doc.go │ │ └── suite_test.go │ │ ├── cilium-crds │ │ ├── cache │ │ │ └── types.go │ │ └── endpoint │ │ │ ├── cell_linux.go │ │ │ ├── endpoint_controller_linux.go │ │ │ ├── endpoint_controller_linux_test.go │ │ │ ├── identitymanager_linux.go │ │ │ ├── identitymanager_linux_test.go │ │ │ └── types.go │ │ ├── metricsconfiguration │ │ ├── metricsconfiguration_controller.go │ │ └── metricsconfiguration_controller_test.go │ │ ├── pod │ │ ├── pod_controller.go │ │ └── pod_controller_test.go │ │ ├── retinaendpoint │ │ ├── retinaendpoint_controller.go │ │ └── retinaendpoint_controller_test.go │ │ └── tracesconfiguration │ │ └── tracesconfiguration_controller.go ├── enricher │ ├── enricher.go │ ├── enricher_test.go │ ├── mock_enricherinterface.go │ └── types.go ├── exporter │ ├── otel_agent.go │ └── prometheusexporter.go ├── hubble │ ├── common │ │ ├── decoder.go │ │ └── decoder_linux.go │ └── parser │ │ ├── layer34 │ │ └── parser_linux.go │ │ ├── parser_linux.go │ │ └── seven │ │ └── parser_linux.go ├── k8s │ ├── apiserver_linux.go │ ├── cell_linux.go │ ├── local_node_synchronizer_linux.go │ ├── placeholders_linux.go │ └── watcher_linux.go ├── label │ └── k8s.go ├── lib │ └── ignore_headers.txt ├── loader │ ├── compile.go │ └── generate.go ├── log │ ├── zap.go │ └── zap_test.go ├── managers │ ├── controllermanager │ │ ├── controllermanager.go │ │ └── controllermanager_test.go │ ├── filtermanager │ │ ├── cache.go │ │ ├── cache_test.go │ │ ├── manager_linux.go │ │ ├── manager_linux_test.go │ │ ├── manager_windows.go │ │ ├── mock_types.go │ │ └── types.go │ ├── pluginmanager │ │ ├── cells_linux.go │ │ ├── pluginmanager.go │ │ └── pluginmanager_test.go │ ├── servermanager │ │ └── servermanager.go │ └── watchermanager │ │ ├── mocks │ │ └── mock_types.go │ │ ├── types.go │ │ ├── watchermanager.go │ │ └── watchermanager_test.go ├── metrics │ ├── interfaces.go │ ├── metrics.go │ ├── metrics_test.go │ ├── mock_types.go │ ├── types.go │ ├── types_linux.go │ └── types_windows.go ├── module │ ├── metrics │ │ ├── basemetricsobject.go │ │ ├── dns.go │ │ ├── dns_test.go │ │ ├── drops.go │ │ ├── drops_test.go │ │ ├── forward.go │ │ ├── forward_test.go │ │ ├── latency.go │ │ ├── latency_test.go │ │ ├── metrics_module.go │ │ ├── metrics_module_linux_test.go │ │ ├── mock_types.go │ │ ├── tcpflags.go │ │ ├── tcpflags_test.go │ │ ├── tcpretrans.go │ │ ├── types.go │ │ └── types_test.go │ └── traces │ │ ├── mock_moduleinterface.go │ │ ├── traces_module.go │ │ └── types.go ├── monitoragent │ ├── cell_linux.go │ └── monitoragent_linux.go ├── plugin │ ├── ciliumeventobserver │ │ ├── ciliumeventobserver_linux.go │ │ ├── ciliumeventobserver_linux_test.go │ │ ├── parser_linux.go │ │ └── types_linux.go │ ├── common │ │ ├── common_linux.go │ │ ├── constants.go │ │ └── mocks │ │ │ └── mock_types.go │ ├── conntrack │ │ ├── _cprog │ │ │ ├── conntrack.c │ │ │ ├── conntrack.h │ │ │ ├── dynamic.h │ │ │ └── placeholder.go │ │ ├── conntrack_bpfel_arm64.go │ │ ├── conntrack_bpfel_arm64.o │ │ ├── conntrack_bpfel_x86.go │ │ ├── conntrack_bpfel_x86.o │ │ ├── conntrack_linux.go │ │ ├── conntrack_linux_test.go │ │ ├── conntrack_windows.go │ │ ├── doc.go │ │ └── types_linux.go │ ├── dns │ │ ├── dns_linux.go │ │ ├── dns_linux_test.go │ │ └── types_linux.go │ ├── dropreason │ │ ├── _cprog │ │ │ ├── drop_reason.c │ │ │ ├── drop_reason.h │ │ │ ├── dynamic.h │ │ │ └── placeholder.go │ │ ├── dropreason_linux.go │ │ ├── dropreason_linux_test.go │ │ ├── ebpfsetup_linux.go │ │ ├── kprobe_bpfel_arm64.go │ │ ├── kprobe_bpfel_arm64.o │ │ ├── kprobe_bpfel_x86.go │ │ ├── kprobe_bpfel_x86.o │ │ ├── mocks │ │ │ └── mock_types_linux.go │ │ └── types_linux.go │ ├── filter │ │ ├── _cprog │ │ │ ├── placeholder.go │ │ │ └── retina_filter.c │ │ ├── filter_bpfel_arm64.go │ │ ├── filter_bpfel_arm64.o │ │ ├── filter_bpfel_x86.go │ │ ├── filter_bpfel_x86.o │ │ ├── filter_map_linux.go │ │ ├── filter_map_linux_test.go │ │ ├── filter_map_windows.go │ │ ├── mocks │ │ │ └── mock_types.go │ │ └── types.go │ ├── hnsstats │ │ ├── hnsstats_windows.go │ │ ├── hnsstats_windows_test.go │ │ ├── types_windows.go │ │ └── vfp_counters_windows.go │ ├── include_linux.go │ ├── include_windows.go │ ├── infiniband │ │ ├── Makefile │ │ ├── filesystem_test.go │ │ ├── infiniband_linux.go │ │ ├── infiniband_linux_test.go │ │ ├── infiniband_mock_generated.go │ │ ├── infiniband_stats_linux.go │ │ ├── infiniband_stats_linux_test.go │ │ └── types_linux.go │ ├── lib │ │ ├── _amd64 │ │ │ ├── placeholder.go │ │ │ └── vmlinux.h │ │ ├── _arm64 │ │ │ ├── placeholder.go │ │ │ └── vmlinux.h │ │ └── common │ │ │ └── libbpf │ │ │ ├── _include │ │ │ ├── asm │ │ │ │ ├── barrier.h │ │ │ │ └── placeholder.go │ │ │ ├── linux │ │ │ │ ├── compiler.h │ │ │ │ ├── err.h │ │ │ │ ├── filter.h │ │ │ │ ├── kernel.h │ │ │ │ ├── list.h │ │ │ │ ├── overflow.h │ │ │ │ ├── placeholder.go │ │ │ │ ├── ring_buffer.h │ │ │ │ └── types.h │ │ │ └── uapi │ │ │ │ └── linux │ │ │ │ ├── bpf.h │ │ │ │ ├── bpf_common.h │ │ │ │ ├── btf.h │ │ │ │ ├── if_link.h │ │ │ │ ├── if_xdp.h │ │ │ │ ├── netdev.h │ │ │ │ ├── netlink.h │ │ │ │ ├── perf_event.h │ │ │ │ ├── pkt_cls.h │ │ │ │ ├── pkt_sched.h │ │ │ │ └── placeholder.go │ │ │ └── _src │ │ │ ├── bpf.c │ │ │ ├── bpf.h │ │ │ ├── bpf_core_read.h │ │ │ ├── bpf_endian.h │ │ │ ├── bpf_gen_internal.h │ │ │ ├── bpf_helper_defs.h │ │ │ ├── bpf_helpers.h │ │ │ ├── bpf_prog_linfo.c │ │ │ ├── bpf_tracing.h │ │ │ ├── btf.c │ │ │ ├── btf.h │ │ │ ├── btf_dump.c │ │ │ ├── btf_iter.c │ │ │ ├── btf_relocate.c │ │ │ ├── elf.c │ │ │ ├── features.c │ │ │ ├── gen_loader.c │ │ │ ├── hashmap.c │ │ │ ├── hashmap.h │ │ │ ├── libbpf.c │ │ │ ├── libbpf.h │ │ │ ├── libbpf_common.h │ │ │ ├── libbpf_errno.c │ │ │ ├── libbpf_internal.h │ │ │ ├── libbpf_legacy.h │ │ │ ├── libbpf_probes.c │ │ │ ├── libbpf_version.h │ │ │ ├── linker.c │ │ │ ├── netlink.c │ │ │ ├── nlattr.c │ │ │ ├── nlattr.h │ │ │ ├── placeholder.go │ │ │ ├── relo_core.c │ │ │ ├── relo_core.h │ │ │ ├── ringbuf.c │ │ │ ├── skel_internal.h │ │ │ ├── str_error.c │ │ │ ├── str_error.h │ │ │ ├── strset.c │ │ │ ├── strset.h │ │ │ ├── usdt.bpf.h │ │ │ ├── usdt.c │ │ │ ├── xsk.c │ │ │ ├── xsk.h │ │ │ ├── zip.c │ │ │ └── zip.h │ ├── linuxutil │ │ ├── Makefile │ │ ├── ethtool_handle_linux.go │ │ ├── ethtool_stats_linux.go │ │ ├── ethtool_stats_linux_test.go │ │ ├── linuxutil_linux.go │ │ ├── linuxutil_linux_test.go │ │ ├── linuxutil_mock_generated_linux.go │ │ ├── netstat_stats_linux.go │ │ ├── netstat_stats_linux_test.go │ │ ├── testdata │ │ │ ├── correct-netstat │ │ │ ├── somecorrect-netstat1 │ │ │ └── wrong-netstat │ │ └── types_linux.go │ ├── mock │ │ └── plugin.go │ ├── mockplugin │ │ └── mockplugin.go │ ├── packetforward │ │ ├── _cprog │ │ │ ├── packetforward.c │ │ │ ├── packetforward.h │ │ │ └── placeholder.go │ │ ├── mocks │ │ │ └── mock_types.go │ │ ├── packetforward_bpfel_arm64.go │ │ ├── packetforward_bpfel_arm64.o │ │ ├── packetforward_bpfel_x86.go │ │ ├── packetforward_bpfel_x86.o │ │ ├── packetforward_linux.go │ │ ├── packetforward_linux_test.go │ │ └── types_linux.go │ ├── packetparser │ │ ├── _cprog │ │ │ ├── dynamic.h │ │ │ ├── packetparser.c │ │ │ ├── packetparser.h │ │ │ └── placeholder.go │ │ ├── mocks │ │ │ └── mock_types_linux.go │ │ ├── packetparser_bpfel_arm64.go │ │ ├── packetparser_bpfel_arm64.o │ │ ├── packetparser_bpfel_x86.go │ │ ├── packetparser_bpfel_x86.o │ │ ├── packetparser_linux.go │ │ ├── packetparser_linux_test.go │ │ └── types_linux.go │ ├── pktmon │ │ └── pktmon_windows.go │ ├── plugin.go │ ├── registry │ │ └── registry.go │ └── tcpretrans │ │ ├── tcpretrans_linux.go │ │ └── types_linux.go ├── provider │ └── azure │ │ └── clients │ │ ├── azclients.go │ │ ├── doc.go │ │ └── types.go ├── pubsub │ ├── mock_pubsubinterface.go │ ├── pubsub.go │ ├── pubsub_test.go │ └── types.go ├── server │ ├── server.go │ └── server_test.go ├── servermanager │ └── cell_linux.go ├── shared │ ├── config │ │ ├── config_linux.go │ │ └── type.go │ └── telemetry │ │ ├── cell_linux.go │ │ └── type.go ├── telemetry │ ├── consts.go │ ├── heartbeat_unix.go │ ├── heartbeat_unix_test.go │ ├── heartbeat_windows.go │ ├── heartbeat_windows_test.go │ ├── noop_perf.go │ ├── noop_telemetry.go │ ├── perf.go │ ├── perf_unix.go │ ├── perf_windows.go │ ├── telemetry.go │ ├── telemetry_test.go │ └── utils.go ├── utils │ ├── attr_utils.go │ ├── common.go │ ├── flow_utils.go │ ├── metadata_linux.pb.go │ ├── metadata_linux.proto │ ├── metadata_windows.pb.go │ ├── metadata_windows.proto │ ├── metric_names.go │ ├── testutil │ │ └── cilium │ │ │ ├── endpoint_client.go │ │ │ ├── errors.go │ │ │ ├── errors_test.go │ │ │ ├── identity_client.go │ │ │ ├── resource.go │ │ │ └── versioned_client.go │ ├── utils_linux.go │ ├── utils_linux_test.go │ └── utils_windows.go └── watchers │ ├── apiserver │ ├── apiserver.go │ ├── apiserver_test.go │ ├── mocks │ │ └── mock_types.go │ └── types.go │ └── endpoint │ ├── endpoint.go │ ├── endpoint_linux.go │ ├── endpoint_linux_test.go │ ├── endpoint_windows.go │ └── types.go ├── samples ├── capture │ ├── capture-specific-pod-on-a-node.yaml │ ├── node-s3upload-aws.yaml │ ├── node-s3upload-minio.yaml │ ├── nodeblobupload.yaml │ └── podblobupload.yaml └── metricsconfiguration.yaml ├── scripts ├── coverage │ ├── README.md │ ├── compare_cov.py │ └── get_coverage.py └── windows.ps1 ├── shell ├── Dockerfile ├── README.md ├── attach.go ├── manifests.go ├── manifests_test.go ├── shell.go └── validation.go ├── site ├── .gitignore ├── README.md ├── babel.config.js ├── docusaurus.config.ts ├── package-lock.json ├── package.json ├── sidebars.ts ├── site │ └── package-lock.json ├── src │ ├── components │ │ ├── Features.module.css │ │ ├── Features.tsx │ │ ├── LandingPage.module.css │ │ ├── LandingPage.tsx │ │ ├── cni.svg │ │ ├── eBPF.svg │ │ ├── hex.svg │ │ ├── hubble-light.svg │ │ ├── kubernetes.svg │ │ ├── prometheus.svg │ │ ├── square1.svg │ │ ├── square2.svg │ │ └── wireshark.svg │ ├── css │ │ └── custom.css │ ├── pages │ │ ├── index.module.css │ │ └── index.tsx │ └── prismColorTheme.ts ├── start-dev.sh ├── static │ └── img │ │ ├── Retina-logo-horizontal-white.png │ │ ├── Retina-logo-horizontal-white.svg │ │ ├── Retina-logo-horizontal.png │ │ ├── Retina-logo-horizontal.svg │ │ ├── Retina-logo-vertical-white.png │ │ ├── Retina-logo-vertical-white.svg │ │ ├── Retina-logo-vertical.png │ │ ├── Retina-logo-vertical.svg │ │ ├── Retina-logo-white.png │ │ ├── Retina-logo-white.svg │ │ ├── Retina-logo.png │ │ ├── Retina-logo.svg │ │ ├── favicon.svg │ │ ├── networking.svg │ │ ├── old-retina-logo.svg │ │ ├── retina-logo-dark.svg │ │ └── retina-social-card.png └── tsconfig.json ├── test ├── e2e │ ├── README.md │ ├── common │ │ └── common.go │ ├── framework │ │ ├── azure │ │ │ ├── create-cluster-with-npm.go │ │ │ ├── create-cluster.go │ │ │ ├── create-rg.go │ │ │ ├── create-vnet.go │ │ │ ├── delete-cluster.go │ │ │ ├── delete-rg.go │ │ │ ├── enable-ama.go │ │ │ ├── get-fqdn.go │ │ │ └── get-kubeconfig.go │ │ ├── generic │ │ │ └── load-tag.go │ │ ├── helpers │ │ │ └── helpers.go │ │ ├── kubernetes │ │ │ ├── check-pod-status.go │ │ │ ├── create-agnhost-statefulset.go │ │ │ ├── create-kapinger-deployment.go │ │ │ ├── create-namespace.go │ │ │ ├── create-network-policy.go │ │ │ ├── create-resource.go │ │ │ ├── delete-namespace.go │ │ │ ├── delete-resource.go │ │ │ ├── exec-pod.go │ │ │ ├── get-external-crd.go │ │ │ ├── get-logs.go │ │ │ ├── get-pod-ip.go │ │ │ ├── install-hubble-helm.go │ │ │ ├── install-retina-helm.go │ │ │ ├── label-nodes.go │ │ │ ├── no-crashes.go │ │ │ ├── port-forward.go │ │ │ ├── portforward.go │ │ │ ├── uninstall-helm.go │ │ │ ├── upgrade-retina-helm.go │ │ │ ├── validate-service.go │ │ │ └── validateHttp.go │ │ ├── params │ │ │ └── params.go │ │ ├── prometheus │ │ │ └── prometheus.go │ │ ├── scaletest │ │ │ ├── add-shared-labels.go │ │ │ ├── add-unique-labels.go │ │ │ ├── create-network-policies.go │ │ │ ├── create-resources.go │ │ │ ├── delete-and-re-add-labels.go │ │ │ ├── get-publish-metrics.go │ │ │ ├── options.go │ │ │ ├── templates │ │ │ │ └── networkpolicy.go │ │ │ ├── validate-nodes.go │ │ │ └── validate-options.go │ │ └── types │ │ │ ├── background_test.go │ │ │ ├── job.go │ │ │ ├── jobvalues.go │ │ │ ├── runner.go │ │ │ ├── scenarios_test.go │ │ │ ├── step.go │ │ │ ├── step_sleep.go │ │ │ └── step_stop.go │ ├── hubble │ │ └── scenario.go │ ├── infra │ │ └── azure_temp_infra_setup.go │ ├── jobs │ │ ├── jobs.go │ │ ├── perf.go │ │ └── scale.go │ ├── retina_e2e_test.go │ ├── retina_perf_test.go │ ├── scale_test.go │ └── scenarios │ │ ├── dns │ │ ├── scenarios.go │ │ ├── validate-advanced-dns-metric.go │ │ └── validate-basic-dns-metric.go │ │ ├── drop │ │ ├── scenario.go │ │ └── validate-drop-metric.go │ │ ├── latency │ │ ├── scenario.go │ │ └── validate-latency-metric.go │ │ ├── perf │ │ ├── get-network-performance-measures.go │ │ ├── get-perf-regression-results.go │ │ └── publish-perf-results.go │ │ ├── tcp │ │ ├── scenario.go │ │ ├── validate-flow-metric.go │ │ └── validate-tcp-connection-remote.go │ │ └── windows │ │ ├── scenario.go │ │ └── validate-hns-metrics.go ├── enricher │ ├── enricher │ └── main_linux.go ├── goldpinger │ ├── cluster-role-binding.yaml │ ├── cluster-role.yaml │ ├── daemonset.yaml │ ├── deployment.yaml │ ├── goldpinger-deny-all.yaml │ ├── service-account.yaml │ └── service.yaml ├── image │ ├── .dockerignore │ └── Dockerfile ├── kind │ └── kind.yaml ├── managers │ └── filtermanager │ │ └── main.go ├── multicloud │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── diagrams │ │ ├── diagram-mc.excalidraw │ │ ├── diagram-mc.svg │ │ ├── diagram.excalidraw │ │ ├── diagram.svg │ │ ├── mc-eks-grafana.png │ │ ├── mc-gke-hubble-ui.png │ │ └── mc-gke-hubble.png │ ├── examples │ │ ├── aks │ │ │ ├── .terraform.lock.hcl │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── providers.tf │ │ │ └── variables.tf │ │ ├── eks │ │ │ ├── .terraform.lock.hcl │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── provider.tf │ │ │ └── variables.tf │ │ ├── gke │ │ │ ├── .terraform.lock.hcl │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── providers.tf │ │ │ └── variables.tf │ │ ├── grafana │ │ │ ├── .terraform.lock.hcl │ │ │ ├── main.tf │ │ │ ├── providers.tf │ │ │ └── variables.tf │ │ ├── integration │ │ │ ├── prometheus-kind │ │ │ │ ├── .terraform.lock.hcl │ │ │ │ ├── main.tf │ │ │ │ ├── outputs.tf │ │ │ │ ├── providers.tf │ │ │ │ └── variables.tf │ │ │ ├── retina-aks │ │ │ │ ├── .terraform.lock.hcl │ │ │ │ ├── main.tf │ │ │ │ ├── outputs.tf │ │ │ │ ├── providers.tf │ │ │ │ └── variables.tf │ │ │ ├── retina-eks │ │ │ │ ├── .terraform.lock.hcl │ │ │ │ ├── main.tf │ │ │ │ ├── outputs.tf │ │ │ │ ├── providers.tf │ │ │ │ └── variables.tf │ │ │ ├── retina-gke │ │ │ │ ├── .terraform.lock.hcl │ │ │ │ ├── main.tf │ │ │ │ ├── outputs.tf │ │ │ │ ├── providers.tf │ │ │ │ └── variables.tf │ │ │ └── retina-kind │ │ │ │ ├── .terraform.lock.hcl │ │ │ │ ├── main.tf │ │ │ │ ├── outputs.tf │ │ │ │ ├── providers.tf │ │ │ │ └── variables.tf │ │ └── kind │ │ │ ├── .terraform.lock.hcl │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── providers.tf │ │ │ └── variables.tf │ ├── live │ │ ├── files │ │ │ ├── mc-demo-eks-coredns-custom.yaml │ │ │ ├── mc-demo-manifests.yaml │ │ │ ├── retina-hubble.yaml │ │ │ ├── retina-standard-advanced-local-operator.yaml │ │ │ ├── retina-standard-advanced-remote-operator.yaml │ │ │ └── retina-standard-basic-mode.yaml │ │ ├── retina-aks │ │ │ ├── .terraform.lock.hcl │ │ │ ├── locals.tf │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── providers.tf │ │ │ └── variables.tf │ │ ├── retina-eks │ │ │ ├── .terraform.lock.hcl │ │ │ ├── locals.tf │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── providers.tf │ │ │ └── variables.tf │ │ ├── retina-gke │ │ │ ├── .terraform.lock.hcl │ │ │ ├── locals.tf │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── providers.tf │ │ │ └── variables.tf │ │ └── retina-kind │ │ │ ├── .terraform.lock.hcl │ │ │ ├── locals.tf │ │ │ ├── main.tf │ │ │ └── providers.tf │ ├── modules │ │ ├── aks │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── provider.tf │ │ │ └── variables.tf │ │ ├── eks │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── provider.tf │ │ │ └── variables.tf │ │ ├── gke │ │ │ ├── main.tf │ │ │ ├── output.tf │ │ │ ├── provider.tf │ │ │ └── variables.tf │ │ ├── grafana-pdc-agent │ │ │ ├── main.tf │ │ │ ├── providers.tf │ │ │ └── variables.tf │ │ ├── grafana │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── providers.tf │ │ │ └── variables.tf │ │ ├── helm-release │ │ │ ├── main.tf │ │ │ ├── provider.tf │ │ │ └── variables.tf │ │ └── kind │ │ │ ├── main.tf │ │ │ ├── output.tf │ │ │ ├── provider.tf │ │ │ └── variables.tf │ └── test │ │ ├── go.mod │ │ ├── go.sum │ │ ├── integration │ │ ├── prometheus_kind_test.go │ │ ├── retina_aks_test.go │ │ ├── retina_eks_test.go │ │ ├── retina_gke_test.go │ │ └── retina_kind_test.go │ │ ├── unit │ │ ├── aks_test.go │ │ ├── eks_test.go │ │ ├── gke_test.go │ │ └── kind_test.go │ │ └── utils │ │ ├── types.go │ │ ├── utils.go │ │ └── utils_test.go ├── plugin │ ├── Makefile │ ├── dns │ │ └── main_linux.go │ ├── dropreason │ │ └── main_linux.go │ ├── infiniband │ │ └── main_linux.go │ ├── linuxutil │ │ └── main_linux.go │ ├── packetforward │ │ └── main_linux.go │ └── packetparser │ │ └── main_linux.go ├── profiles │ ├── advanced │ │ ├── crd │ │ │ └── metrics_config_crd.yaml │ │ └── values.yaml │ ├── basic │ │ ├── crd │ │ │ └── .gitkeep │ │ └── values.yaml │ └── localctx │ │ ├── crd │ │ └── .gitkeep │ │ └── values.yaml ├── prometheus │ ├── ama-metrics-node │ │ └── prometheus-config │ ├── ama-metrics │ │ └── prometheus-config │ ├── create-cm.sh │ └── service.yaml ├── retry │ └── retry.go ├── scale │ ├── README.md │ ├── cpu-and-mem.sh │ ├── create-all.sh │ ├── create-crb.sh │ ├── create-deployments.sh │ ├── create-netpols.sh │ ├── create-ns.sh │ ├── create-sa.sh │ ├── example-clusterrolebinding.yaml │ ├── example-deployment.yaml │ ├── example-netpol.yaml │ ├── example-serviceaccount.yaml │ ├── generate-yamls.sh │ ├── pprof.sh │ ├── restarts.sh │ ├── scale-deployments.sh │ └── scrape-metrics.sh ├── testcrds │ └── metrics-config-goldpinger.yaml ├── trafficgen │ ├── agnhost.yaml │ ├── deny.yaml │ └── kapinger.yaml ├── utsummary │ └── main.go └── watchers │ ├── apiserver │ └── main.go │ └── veth │ ├── deployment.yaml │ └── main.go └── windows ├── docker ├── DockerBuild.ps1 ├── DockerBuildModule.psm1 └── notes.md ├── kubeconfigtemplate.yaml ├── manifests ├── node-selector-patch.yaml └── windows.yaml ├── readme.md └── setkubeconfigpath.ps1 /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "retina", 3 | "image": "mcr.microsoft.com/devcontainers/base:jammy", 4 | "features": { 5 | "ghcr.io/devcontainers/features/common-utils:2": {}, 6 | "ghcr.io/devcontainers/features/docker-in-docker:2": {}, 7 | "ghcr.io/devcontainers/features/github-cli:1": {}, 8 | "ghcr.io/devcontainers/features/go:1": {}, 9 | "ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {}, 10 | "ghcr.io/devcontainers-contrib/features/kind:1": {}, 11 | "ghcr.io/devcontainers/features/azure-cli:1": {} 12 | }, 13 | "postCreateCommand": "bash .devcontainer/installMoreTools.sh && kind create cluster", 14 | "customizations": { 15 | "vscode": { 16 | "extensions": [ 17 | "esbenp.prettier-vscode", 18 | "golang.go", 19 | "mutantdino.resourcemonitor", 20 | "ms-vscode.makefile-tools", 21 | "ms-kubernetes-tools.vscode-kubernetes-tools" 22 | ] 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.devcontainer/installMoreTools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install the required tools and dependencies 4 | sudo apt-get update && sudo apt-get install -y lsb-release wget software-properties-common gnupg clang-14 lldb-14 lld-14 clangd-14 man-db 5 | 6 | # Install LLVM 14 7 | export LLVM_VERSION=14 8 | curl -sL https://apt.llvm.org/llvm.sh | sudo bash -s "$LLVM_VERSION" 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | pkg/plugin/lib/** linguist-vendored=true 2 | 3 | *.go text eol=lf 4 | -------------------------------------------------------------------------------- /.github/.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD013": false, 3 | "MD010": false, 4 | "MD033": false, 5 | "MD024": { 6 | "siblings_only": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @microsoft/retina 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 16 | 1. Go to '...' 17 | 2. Click on '....' 18 | 3. Scroll down to '....' 19 | 4. See error 20 | 21 | **Expected behavior** 22 | A clear and concise description of what you expected to happen. 23 | 24 | **Screenshots** 25 | If applicable, add screenshots to help explain your problem. 26 | 27 | **Platform (please complete the following information):** 28 | 29 | - OS: [e.g. AzureLinux] 30 | - Kubernetes Version: [e.g. 1.22] 31 | - Host: [e.g. AKS, KIND, self-host, etc] 32 | - Retina Version: 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "docker" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | reviewers: 8 | - "microsoft/retina" 9 | commit-message: 10 | prefix: "deps" 11 | labels: ["area/infra", "area/dependencies"] 12 | open-pull-requests-limit: 10 13 | - package-ecosystem: "github-actions" 14 | directory: "/" 15 | schedule: 16 | interval: "daily" 17 | reviewers: 18 | - "microsoft/retina" 19 | commit-message: 20 | prefix: "deps" 21 | labels: ["area/infra", "area/dependencies"] 22 | open-pull-requests-limit: 10 23 | - package-ecosystem: "gomod" 24 | directory: "/" 25 | schedule: 26 | interval: "daily" 27 | reviewers: 28 | - "microsoft/retina" 29 | commit-message: 30 | prefix: "deps" 31 | labels: ["lang/go", "area/dependencies"] 32 | ignore: 33 | - dependency-name: "github.com/inspektor-gadget/inspektor-gadget" 34 | open-pull-requests-limit: 10 35 | -------------------------------------------------------------------------------- /.github/workflows/daily-scale-test.yaml: -------------------------------------------------------------------------------- 1 | name: Daily Scale Test 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | 7 | permissions: 8 | contents: read 9 | id-token: write 10 | 11 | jobs: 12 | call-scale-test: 13 | uses: ./.github/workflows/scale-test.yaml 14 | with: 15 | num_deployments: 1000 16 | num_replicas: 20 17 | num_netpol: 0 18 | num_nodes: 1000 19 | cleanup: true 20 | secrets: inherit 21 | -------------------------------------------------------------------------------- /.github/workflows/markdownlint.yaml: -------------------------------------------------------------------------------- 1 | name: Markdown Lint 2 | on: 3 | merge_group: 4 | pull_request: 5 | branches: [main] 6 | jobs: 7 | markdownlint: 8 | if: ${{ github.event_name != 'merge_group' }} 9 | name: markdownlint 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout repository 13 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 14 | - uses: DavidAnson/markdownlint-cli2-action@v9 15 | with: 16 | command: config 17 | globs: | 18 | .github/.markdownlint.json 19 | **/*.md 20 | -------------------------------------------------------------------------------- /.github/workflows/test-multicloud.yml: -------------------------------------------------------------------------------- 1 | name: Test Multicloud 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'test/multicloud/**' 7 | 8 | jobs: 9 | multicloud-test: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: opentofu/setup-opentofu@v1 14 | with: 15 | tofu_version: 1.8.3 16 | 17 | - name: Checkout code 18 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 19 | 20 | - name: Set up Go 21 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 22 | with: 23 | go-version-file: go.mod 24 | 25 | - name: Install dependencies 26 | run: go mod download 27 | working-directory: test/multicloud/ 28 | 29 | - name: Run tests 30 | run: make test 31 | working-directory: test/multicloud/ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # If you prefer the allow list template instead of the deny list, see community template: 2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore 3 | # 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Avoid checking in keys 12 | *.pem 13 | 14 | # Test binary, built with `go test -c` 15 | *.test 16 | 17 | # Output of the go coverage tool, specifically when used with LiteIDE 18 | *.out 19 | 20 | # Dependency directories (remove the comment below to include it) 21 | # vendor/ 22 | 23 | # Go workspace file 24 | go.work 25 | 26 | # Object files 27 | *.o 28 | 29 | # docusaurus 30 | site/yarn.lock 31 | site/.docusaurus/ 32 | site/node_modules/ 33 | 34 | output 35 | #vscode 36 | .vscode/ 37 | 38 | dist/ 39 | bin/ 40 | 41 | image-metadata-*.json 42 | *packetmonitorsupport*/ 43 | *.pem 44 | *results*.json 45 | netperf-*.json 46 | netperf-*.csv 47 | 48 | .certs/ 49 | 50 | artifacts/ 51 | -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://goreleaser.com/static/schema.json 2 | # vim: set ts=2 sw=2 tw=0 fo=cnqoj 3 | 4 | version: 2 5 | 6 | before: 7 | hooks: 8 | # You may remove this if you don't use go modules. 9 | - go mod tidy 10 | 11 | builds: 12 | - binary: kubectl-retina-{{ .Os }}-{{ .Arch }} 13 | env: 14 | - CGO_ENABLED=0 15 | goarch: 16 | - amd64 17 | - arm64 18 | gcflags: 19 | - -dwarflocationlists=true 20 | goos: 21 | - linux 22 | - windows 23 | - darwin 24 | ldflags: 25 | - -X github.com/microsoft/retina/internal/buildinfo.Version=v{{.Version}} 26 | main: cli/main.go 27 | 28 | archives: 29 | - name_template: "{{ .Binary }}-v{{ .Version }}" 30 | wrap_in_directory: false 31 | format_overrides: 32 | - goos: windows 33 | format: zip 34 | 35 | changelog: 36 | sort: asc 37 | filters: 38 | exclude: 39 | - "^docs:" 40 | - "^test:" 41 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ## How to file issues and get help 4 | 5 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing issues before filing new issues to avoid duplicates. For new issues, file your bug or feature request as a new Issue. 6 | 7 | ## Microsoft Support Policy 8 | 9 | Support for this project is limited to the resources listed above. 10 | -------------------------------------------------------------------------------- /captureworkload/README.md: -------------------------------------------------------------------------------- 1 | # Retina Capture 2 | 3 | This directory serves as the entrypoint to Retina Capture: a wrapper to handle lifecyle of packet capture workload 4 | 5 | ## Build 6 | 7 | ```bash 8 | make retina-capture-workload 9 | ``` 10 | 11 | ## Test 12 | 13 | ```bash 14 | HOSTPATH="/tmp/" CAPTURE_NAME="out" CAPTURE_DURATION="10s" output/linux_amd64/retina/captureworkload 15 | ``` 16 | 17 | ## Release 18 | 19 | ```bash 20 | make retina-image 21 | make retina-image-push 22 | ``` 23 | -------------------------------------------------------------------------------- /cli/README.md: -------------------------------------------------------------------------------- 1 | # Retina CLI 2 | 3 | This directory serves as the entrypoint to Retina CLI 4 | 5 | ## Tools 6 | 7 | ### trace 8 | 9 | Trace subcommand retrieve status or results from Retina. 10 | 11 | ### Config 12 | 13 | Config subcommand configures retina CLI. 14 | 15 | ### Capture 16 | 17 | Capture subcommand allows the user to collect networking resources on a Kubernetes cluster. 18 | -------------------------------------------------------------------------------- /cli/cmd/capture/capture.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package capture 5 | 6 | import ( 7 | "github.com/microsoft/retina/cli/cmd" 8 | "github.com/spf13/cobra" 9 | "k8s.io/cli-runtime/pkg/genericclioptions" 10 | ) 11 | 12 | var opts = struct { 13 | genericclioptions.ConfigFlags 14 | Name *string 15 | }{ 16 | Name: new(string), 17 | } 18 | 19 | const defaultName = "retina-capture" 20 | 21 | var capture = &cobra.Command{ 22 | Use: "capture", 23 | Short: "Capture network traffic", 24 | } 25 | 26 | func init() { 27 | cmd.Retina.AddCommand(capture) 28 | opts.ConfigFlags = *genericclioptions.NewConfigFlags(true) 29 | opts.AddFlags(capture.PersistentFlags()) 30 | capture.PersistentFlags().StringVar(opts.Name, "name", defaultName, "The name of the Retina Capture") 31 | } 32 | -------------------------------------------------------------------------------- /cli/cmd/trace.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package cmd 4 | 5 | import ( 6 | "github.com/pkg/errors" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | var trace = &cobra.Command{ 11 | Use: "trace", 12 | Short: "Retrieve status or results from Retina", 13 | } 14 | 15 | var getTrace = &cobra.Command{ 16 | Use: "get", 17 | Short: "Retrieve network trace results with operation ID", 18 | RunE: func(cmd *cobra.Command, _ []string) error { 19 | operationID, _ := cmd.Flags().GetString("operationID") 20 | return errors.Wrap(RetinaClient.GetTrace(operationID), "failed to get traces") 21 | }, 22 | } 23 | 24 | func init() { 25 | getTrace.Flags().String("operationID", "", "Network Trace Operation ID") 26 | _ = getTrace.MarkFlagRequired("operationID") 27 | trace.AddCommand(getTrace) 28 | Retina.AddCommand(trace) 29 | } 30 | -------------------------------------------------------------------------------- /cli/cmd/version.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package cmd 5 | 6 | import ( 7 | "fmt" 8 | 9 | "github.com/spf13/cobra" 10 | 11 | "github.com/microsoft/retina/internal/buildinfo" 12 | ) 13 | 14 | var version = &cobra.Command{ 15 | Use: "version", 16 | Short: "Show version", 17 | Run: func(*cobra.Command, []string) { 18 | fmt.Println(buildinfo.Version) 19 | }, 20 | } 21 | 22 | func init() { 23 | Retina.AddCommand(version) 24 | } 25 | -------------------------------------------------------------------------------- /cli/cmd_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | 7 | "github.com/microsoft/retina/cli/cmd" 8 | "github.com/spf13/cobra" 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func ExecuteInTest(cmd *cobra.Command, args []string) (stdout string, stderr string, err error) { 14 | var stdoutBuf, stderrBuf bytes.Buffer 15 | cmd.SetArgs(args) 16 | cmd.SetOut(&stdoutBuf) 17 | cmd.SetErr(&stderrBuf) 18 | defer func() { 19 | cmd.SetArgs(nil) 20 | cmd.SetOut(nil) 21 | cmd.SetErr(nil) 22 | }() 23 | 24 | err = cmd.Execute() 25 | return stdoutBuf.String(), stderrBuf.String(), err 26 | } 27 | 28 | func TestCLICmd(t *testing.T) { 29 | stdout, stderr, err := ExecuteInTest(cmd.Retina, []string{"-h"}) 30 | require.NoError(t, err) 31 | assert.Contains(t, stdout, "kubectl-retina") 32 | assert.Equal(t, stderr, "") 33 | } 34 | -------------------------------------------------------------------------------- /cli/main.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | 9 | "github.com/microsoft/retina/cli/cmd" 10 | _ "github.com/microsoft/retina/cli/cmd/capture" 11 | ) 12 | 13 | func main() { 14 | if err := cmd.Retina.Execute(); err != nil { 15 | fmt.Println(err) 16 | os.Exit(1) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /cmd/hubble_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package cmd 4 | 5 | import ( 6 | "fmt" 7 | 8 | "github.com/cilium/cilium/pkg/hive" 9 | "github.com/microsoft/retina/cmd/hubble" 10 | "github.com/microsoft/retina/internal/buildinfo" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | var ( 15 | h = hive.New(hubble.Agent) 16 | 17 | hubbleCmd = &cobra.Command{ 18 | Use: "hubble-control-plane", 19 | Short: "Start Hubble control plane", 20 | Run: func(cobraCmd *cobra.Command, _ []string) { 21 | if v, _ := cobraCmd.Flags().GetBool("version"); v { 22 | fmt.Printf("%s %s\n", cobraCmd.Name(), buildinfo.Version) 23 | } 24 | hubble.Execute(cobraCmd, h) 25 | }, 26 | } 27 | ) 28 | 29 | func init() { 30 | h.RegisterFlags(hubbleCmd.Flags()) 31 | hubbleCmd.AddCommand(h.Command()) 32 | 33 | hubble.InitGlobalFlags(hubbleCmd, h.Viper()) 34 | 35 | rootCmd.AddCommand(hubbleCmd) 36 | } 37 | -------------------------------------------------------------------------------- /cmd/standard/daemon_linux.go: -------------------------------------------------------------------------------- 1 | package standard 2 | 3 | import "github.com/cilium/ebpf/rlimit" 4 | 5 | func (d *Daemon) RemoveMemlock() error { 6 | return rlimit.RemoveMemlock() 7 | } 8 | -------------------------------------------------------------------------------- /cmd/standard/daemon_windows.go: -------------------------------------------------------------------------------- 1 | package standard 2 | 3 | func (d *Daemon) RemoveMemlock() error { 4 | // This function is a no-op on Windows. 5 | return nil 6 | } 7 | -------------------------------------------------------------------------------- /controller/Dockerfile.proto: -------------------------------------------------------------------------------- 1 | # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" 2 | FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:5341a0010ecff114ee2f11f5eaa4f73b721b54142954041523f3e785d5c4b978 3 | 4 | LABEL Name=retina-builder Version=0.0.1 5 | 6 | RUN tdnf install -y unzip 7 | 8 | WORKDIR /tmp 9 | 10 | RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.34.2 11 | RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v24.2/protoc-24.2-linux-x86_64.zip 12 | RUN unzip protoc-24.2-linux-x86_64.zip -d protoc 13 | RUN mv protoc/bin/protoc /usr/bin/protoc 14 | 15 | WORKDIR /app 16 | ENTRYPOINT protoc -I=. --go_out=paths=source_relative:. ./pkg/utils/metadata_linux.proto 17 | -------------------------------------------------------------------------------- /controller/Dockerfile.windows-native.dockerignore: -------------------------------------------------------------------------------- 1 | pkg/plugin/windows/pktmon/packetmonitorsupport/* 2 | *.tar 3 | -------------------------------------------------------------------------------- /controller/main.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package main 4 | 5 | import ( 6 | "github.com/microsoft/retina/cmd" 7 | ) 8 | 9 | func main() { 10 | cmd.Execute() 11 | } 12 | -------------------------------------------------------------------------------- /crd/Makefile: -------------------------------------------------------------------------------- 1 | .DEFAULT_GOAL = all 2 | 3 | REPO_ROOT = $(shell git rev-parse --show-toplevel) 4 | CONTROLLER_GEN = go tool sigs.k8s.io/controller-tools/cmd/controller-gen 5 | HELM_CRD_DIR = $(REPO_ROOT)/deploy/standard/manifests/controller/helm/retina/crds 6 | 7 | .PHONY: generate manifests 8 | 9 | all: generate manifests 10 | 11 | generate: 12 | $(CONTROLLER_GEN) object paths="./api/..." 13 | 14 | manifests: 15 | rm -rf $(HELM_CRD_DIR) 16 | $(CONTROLLER_GEN) crd paths="./api/..." output:crd:artifacts:config=$(HELM_CRD_DIR) 17 | 18 | -------------------------------------------------------------------------------- /crd/README.md: -------------------------------------------------------------------------------- 1 | # Retina CRDs 2 | 3 | This package contains the CRD definitions for Retina 4 | -------------------------------------------------------------------------------- /crd/api/v1alpha1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | //go:build !ignore_uncovered 2 | // +build !ignore_uncovered 3 | 4 | // Package v1alpha1 contains API Schema definitions for the retina v1alpha1 API group 5 | // +kubebuilder:object:generate=true 6 | // +groupName=retina.sh 7 | package v1alpha1 8 | 9 | import ( 10 | "k8s.io/apimachinery/pkg/runtime/schema" 11 | "sigs.k8s.io/controller-runtime/pkg/scheme" 12 | ) 13 | 14 | var ( 15 | // GroupVersion is group version used to register these objects 16 | GroupVersion = schema.GroupVersion{Group: "retina.sh", Version: "v1alpha1"} 17 | 18 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 19 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 20 | 21 | // AddToScheme adds the types in this group-version to the given scheme. 22 | AddToScheme = SchemeBuilder.AddToScheme 23 | ) 24 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.agent.enabled -}} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | name: retina-cluster-reader-binding 6 | namespace: {{ .Values.namespace }} 7 | subjects: 8 | - kind: ServiceAccount 9 | name: retina-agent 10 | namespace: {{ .Values.namespace }} 11 | roleRef: 12 | kind: ClusterRole 13 | name: retina-cluster-reader 14 | apiGroup: rbac.authorization.k8s.io 15 | 16 | {{- end}} -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/agent/service.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.agent.enabled -}} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: {{ include "retina.fullname" . }} 6 | namespace: {{ .Values.namespace }} 7 | labels: 8 | app: {{ include "retina.name" . }} 9 | spec: 10 | ports: 11 | - port: {{ .Values.service.port }} 12 | targetPort: {{ .Values.retinaPort }} 13 | selector: 14 | app: {{ include "retina.name" . }} 15 | 16 | {{- end}} 17 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/agent/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.agent.enabled -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ .Values.serviceAccount.name }} 6 | namespace: {{ .Values.namespace }} 7 | 8 | {{- end}} 9 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble-relay/metrics-service.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.hubble.enabled .Values.hubble.relay.enabled .Values.hubble.relay.prometheus.enabled }} 2 | # We use a separate service from hubble-relay which can be exposed externally 3 | kind: Service 4 | apiVersion: v1 5 | metadata: 6 | name: hubble-relay-metrics 7 | namespace: {{ .Release.Namespace }} 8 | {{- with .Values.hubble.relay.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | labels: 13 | k8s-app: hubble-relay 14 | spec: 15 | clusterIP: None 16 | type: ClusterIP 17 | selector: 18 | k8s-app: hubble-relay 19 | ports: 20 | - name: metrics 21 | port: {{ .Values.hubble.relay.prometheus.port }} 22 | protocol: TCP 23 | targetPort: prometheus 24 | {{- end }} 25 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble-relay/poddisruptionbudget.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.hubble.enabled .Values.hubble.relay.enabled .Values.hubble.relay.podDisruptionBudget.enabled }} 2 | {{- $component := .Values.hubble.relay.podDisruptionBudget }} 3 | apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} 4 | kind: PodDisruptionBudget 5 | metadata: 6 | name: hubble-relay 7 | namespace: {{ .Release.Namespace }} 8 | {{- with .Values.hubble.relay.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | labels: 13 | k8s-app: hubble-relay 14 | app.kubernetes.io/name: hubble-relay 15 | app.kubernetes.io/part-of: cilium 16 | spec: 17 | {{- with $component.maxUnavailable }} 18 | maxUnavailable: {{ . }} 19 | {{- end }} 20 | {{- with $component.minAvailable }} 21 | minAvailable: {{ . }} 22 | {{- end }} 23 | selector: 24 | matchLabels: 25 | k8s-app: hubble-relay 26 | {{- end }} 27 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble-relay/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.hubble.enabled .Values.hubble.relay.enabled .Values.serviceAccounts.relay.create }} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ .Values.serviceAccounts.relay.name | quote }} 6 | namespace: {{ .Release.Namespace }} 7 | {{- if or .Values.serviceAccounts.relay.annotations .Values.hubble.relay.annotations }} 8 | annotations: 9 | {{- with .Values.hubble.relay.annotations }} 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- with .Values.serviceAccounts.relay.annotations }} 13 | {{- toYaml . | nindent 4 }} 14 | {{- end }} 15 | {{- end }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble-ui/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled .Values.serviceAccounts.ui.create }} 2 | kind: ClusterRoleBinding 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | metadata: 5 | name: hubble-ui 6 | {{- with .Values.hubble.ui.annotations }} 7 | annotations: 8 | {{- toYaml . | nindent 4 }} 9 | {{- end }} 10 | labels: 11 | app.kubernetes.io/part-of: cilium 12 | roleRef: 13 | apiGroup: rbac.authorization.k8s.io 14 | kind: ClusterRole 15 | name: hubble-ui 16 | subjects: 17 | - kind: ServiceAccount 18 | name: {{ .Values.serviceAccounts.ui.name | quote }} 19 | namespace: {{ .Release.Namespace }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble-ui/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled }} 2 | --- 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: hubble-ui-nginx 7 | namespace: {{ .Release.Namespace }} 8 | {{- with .Values.hubble.ui.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | data: 13 | nginx.conf: {{ include "hubble-ui.nginx.conf" . | trim | quote }} 14 | {{- end }} 15 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble-ui/poddisruptionbudget.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled .Values.hubble.ui.podDisruptionBudget.enabled }} 2 | {{- $component := .Values.hubble.ui.podDisruptionBudget }} 3 | apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} 4 | kind: PodDisruptionBudget 5 | metadata: 6 | name: hubble-ui 7 | namespace: {{ .Release.Namespace }} 8 | {{- with .Values.hubble.ui.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | labels: 13 | k8s-app: hubble-ui 14 | app.kubernetes.io/name: hubble-ui 15 | app.kubernetes.io/part-of: cilium 16 | spec: 17 | {{- with $component.maxUnavailable }} 18 | maxUnavailable: {{ . }} 19 | {{- end }} 20 | {{- with $component.minAvailable }} 21 | minAvailable: {{ . }} 22 | {{- end }} 23 | selector: 24 | matchLabels: 25 | k8s-app: hubble-ui 26 | {{- end }} 27 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble-ui/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled .Values.serviceAccounts.ui.create }} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ .Values.serviceAccounts.ui.name | quote }} 6 | namespace: {{ .Release.Namespace }} 7 | {{- if or .Values.serviceAccounts.ui.annotations .Values.hubble.ui.annotations }} 8 | annotations: 9 | {{- with .Values.hubble.ui.annotations }} 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- with .Values.serviceAccounts.ui.annotations }} 13 | {{- toYaml . | nindent 4 }} 14 | {{- end }} 15 | {{- end }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble/peer-service.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.agent .Values.hubble.enabled }} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: hubble-peer 6 | namespace: {{ .Release.Namespace }} 7 | {{- with .Values.hubble.annotations }} 8 | annotations: 9 | {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | labels: 12 | k8s-app: retina 13 | app.kubernetes.io/part-of: retina 14 | app.kubernetes.io/name: hubble-peer 15 | spec: 16 | selector: 17 | k8s-app: retina 18 | ports: 19 | - name: peer-service 20 | {{- if .Values.hubble.peerService.servicePort }} 21 | port: {{ .Values.hubble.peerService.servicePort }} 22 | {{- else }} 23 | port: {{ .Values.hubble.tls.enabled | ternary 443 80 }} 24 | {{- end }} 25 | protocol: TCP 26 | targetPort: {{ .Values.hubble.peerService.targetPort }} 27 | {{- if semverCompare ">=1.22-0" .Capabilities.KubeVersion.GitVersion }} 28 | internalTrafficPolicy: Local 29 | {{- end }} 30 | {{- end }} 31 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-certmanager/relay-client-secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "certmanager") .Values.hubble.relay.enabled }} 2 | --- 3 | apiVersion: cert-manager.io/v1 4 | kind: Certificate 5 | metadata: 6 | name: hubble-relay-client-certs 7 | namespace: {{ .Release.Namespace }} 8 | {{- with .Values.hubble.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | spec: 13 | issuerRef: 14 | {{- toYaml .Values.hubble.tls.auto.certManagerIssuerRef | nindent 4 }} 15 | secretName: hubble-relay-client-certs 16 | commonName: "*.hubble-relay.cilium.io" 17 | dnsNames: 18 | - "*.hubble-relay.cilium.io" 19 | duration: {{ printf "%dh0m0s" (mul .Values.hubble.tls.auto.certValidityDuration 24) }} 20 | privateKey: 21 | rotationPolicy: Always 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-certmanager/ui-client-certs.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "certmanager") .Values.hubble.ui.enabled .Values.hubble.relay.enabled .Values.hubble.relay.tls.server.enabled }} 2 | --- 3 | apiVersion: cert-manager.io/v1 4 | kind: Certificate 5 | metadata: 6 | name: hubble-ui-client-certs 7 | namespace: {{ .Release.Namespace }} 8 | {{- with .Values.hubble.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | spec: 13 | issuerRef: 14 | {{- toYaml .Values.hubble.tls.auto.certManagerIssuerRef | nindent 4 }} 15 | secretName: hubble-ui-client-certs 16 | commonName: "*.hubble-ui.cilium.io" 17 | dnsNames: 18 | - "*.hubble-ui.cilium.io" 19 | duration: {{ printf "%dh0m0s" (mul .Values.hubble.tls.auto.certValidityDuration 24) }} 20 | privateKey: 21 | rotationPolicy: Always 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/job.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "cronJob") }} 2 | --- 3 | apiVersion: batch/v1 4 | kind: Job 5 | metadata: 6 | name: hubble-generate-certs 7 | namespace: {{ .Release.Namespace }} 8 | labels: 9 | k8s-app: hubble-generate-certs 10 | app.kubernetes.io/name: hubble-generate-certs 11 | app.kubernetes.io/part-of: cilium 12 | annotations: 13 | {{- with .Values.certgen.annotations.job }} 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | {{- with .Values.hubble.annotations }} 17 | {{- toYaml . | nindent 4 }} 18 | {{- end }} 19 | {{ include "hubble-generate-certs.job.spec" . }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/rolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "cronJob") .Values.serviceAccounts.hubblecertgen.create }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: RoleBinding 4 | metadata: 5 | name: hubble-generate-certs 6 | namespace: {{ .Release.Namespace }} 7 | {{- with .Values.hubble.annotations }} 8 | annotations: 9 | {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | labels: 12 | app.kubernetes.io/part-of: cilium 13 | roleRef: 14 | apiGroup: rbac.authorization.k8s.io 15 | kind: ClusterRole 16 | name: hubble-generate-certs 17 | subjects: 18 | - kind: ServiceAccount 19 | name: {{ .Values.serviceAccounts.hubblecertgen.name | quote }} 20 | namespace: {{ .Release.Namespace }} 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "cronJob") .Values.serviceAccounts.hubblecertgen.create }} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ .Values.serviceAccounts.hubblecertgen.name | quote }} 6 | namespace: {{ .Release.Namespace }} 7 | {{- if or .Values.serviceAccounts.hubblecertgen.annotations .Values.hubble.annotations }} 8 | annotations: 9 | {{- with .Values.hubble.annotations }} 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- with .Values.serviceAccounts.hubblecertgen.annotations }} 13 | {{- toYaml . | nindent 4 }} 14 | {{- end }} 15 | {{- end }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-helm/relay-client-secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "helm") .Values.hubble.relay.enabled }} 2 | {{- $_ := include "hubble-generate-certs.helm.setup-ca" . -}} 3 | {{- $cn := "*.hubble-relay.cilium.io" }} 4 | {{- $dns := list $cn }} 5 | {{- $cert := genSignedCert $cn nil $dns (.Values.hubble.tls.auto.certValidityDuration | int) .ca -}} 6 | --- 7 | apiVersion: v1 8 | kind: Secret 9 | metadata: 10 | name: hubble-relay-client-certs 11 | namespace: {{ .Release.Namespace }} 12 | {{- with .Values.hubble.annotations }} 13 | annotations: 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | type: kubernetes.io/tls 17 | data: 18 | ca.crt: {{ .ca.Cert | b64enc }} 19 | tls.crt: {{ $cert.Cert | b64enc }} 20 | tls.key: {{ $cert.Key | b64enc }} 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-helm/ui-client-certs.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "helm") .Values.hubble.ui.enabled .Values.hubble.relay.enabled .Values.hubble.relay.tls.server.enabled }} 2 | {{- $_ := include "hubble-generate-certs.helm.setup-ca" . -}} 3 | {{- $cn := "*.hubble-ui.cilium.io" }} 4 | {{- $dns := list $cn }} 5 | {{- $cert := genSignedCert $cn nil $dns (.Values.hubble.tls.auto.certValidityDuration | int) .ca -}} 6 | --- 7 | apiVersion: v1 8 | kind: Secret 9 | metadata: 10 | name: hubble-ui-client-certs 11 | namespace: {{ .Release.Namespace }} 12 | {{- with .Values.hubble.annotations }} 13 | annotations: 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | type: kubernetes.io/tls 17 | data: 18 | ca.crt: {{ .ca.Cert | b64enc }} 19 | tls.crt: {{ $cert.Cert | b64enc }} 20 | tls.key: {{ $cert.Key | b64enc }} 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-provided/relay-client-secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled (not .Values.hubble.tls.auto.enabled) .Values.hubble.relay.enabled }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: hubble-relay-client-certs 6 | namespace: {{ .Release.Namespace }} 7 | {{- with .Values.hubble.annotations }} 8 | annotations: 9 | {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | type: kubernetes.io/tls 12 | data: 13 | ca.crt: {{ .Values.tls.ca.cert }} 14 | tls.crt: {{ .Values.hubble.relay.tls.client.cert | required "missing hubble.relay.tls.client.cert" }} 15 | tls.key: {{ .Values.hubble.relay.tls.client.key | required "missing hubble.relay.tls.client.key" }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-provided/relay-server-secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled (not .Values.hubble.tls.auto.enabled) .Values.hubble.relay.enabled .Values.hubble.relay.tls.server.enabled }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: hubble-relay-server-certs 6 | namespace: {{ .Release.Namespace }} 7 | {{- with .Values.hubble.annotations }} 8 | annotations: 9 | {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | type: kubernetes.io/tls 12 | data: 13 | ca.crt: {{ .Values.tls.ca.cert }} 14 | tls.crt: {{ .Values.hubble.relay.tls.server.cert | required "missing hubble.relay.tls.server.cert" }} 15 | tls.key: {{ .Values.hubble.relay.tls.server.key | required "missing hubble.relay.tls.server.key" }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-provided/server-secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.agent .Values.hubble.enabled .Values.hubble.tls.enabled (not .Values.hubble.tls.auto.enabled) }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: hubble-server-certs 6 | namespace: {{ .Release.Namespace }} 7 | {{- with .Values.hubble.annotations }} 8 | annotations: 9 | {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | type: kubernetes.io/tls 12 | data: 13 | ca.crt: {{ .Values.tls.ca.cert }} 14 | tls.crt: {{ .Values.hubble.tls.server.cert | required "missing hubble.tls.server.cert" }} 15 | tls.key: {{ .Values.hubble.tls.server.key | required "missing hubble.tls.server.key" }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-provided/ui-client-certs.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled (not .Values.hubble.tls.auto.enabled) .Values.hubble.ui.enabled .Values.hubble.relay.enabled .Values.hubble.relay.tls.server.enabled }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: hubble-ui-client-certs 6 | namespace: {{ .Release.Namespace }} 7 | {{- with .Values.hubble.annotations }} 8 | annotations: 9 | {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | type: kubernetes.io/tls 12 | data: 13 | ca.crt: {{ .Values.tls.ca.cert }} 14 | tls.crt: {{ .Values.hubble.ui.tls.client.cert | required "missing hubble.ui.tls.client.cert" }} 15 | tls.key: {{ .Values.hubble.ui.tls.client.key | required "missing hubble.ui.tls.client.key" }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/operator/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.operator.enabled -}} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: clusterrolebinding 7 | app.kubernetes.io/instance: retina-operator-rolebinding 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: operator 10 | app.kubernetes.io/part-of: operator 11 | app.kubernetes.io/managed-by: kustomize 12 | name: retina-operator-rolebinding 13 | roleRef: 14 | apiGroup: rbac.authorization.k8s.io 15 | kind: ClusterRole 16 | name: retina-operator-role 17 | subjects: 18 | - kind: ServiceAccount 19 | name: retina-operator 20 | namespace: {{ .Values.namespace }} 21 | 22 | {{- end -}} 23 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/operator/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.operator.enabled -}} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: retina-operator-config 6 | namespace: {{ .Values.namespace }} 7 | data: 8 | enable-telemetry: {{ .Values.enableTelemetry | quote }} 9 | log-opt: "{\"level\":\"{{ .Values.logLevel }}\"}" 10 | leader-election: {{ .Values.operator.leaderElection | quote }} 11 | identity-gc-interval: {{ .Values.operator.identityGCInterval }} 12 | cilium-endpoint-gc-interval: {{ .Values.operator.endpointGCInterval }} 13 | 14 | {{- end -}} 15 | -------------------------------------------------------------------------------- /deploy/hubble/manifests/controller/helm/retina/templates/operator/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.operator.enabled -}} 2 | 3 | apiVersion: v1 4 | kind: ServiceAccount 5 | metadata: 6 | labels: 7 | app.kubernetes.io/name: serviceaccount 8 | app.kubernetes.io/instance: retina-operator 9 | app.kubernetes.io/component: rbac 10 | app.kubernetes.io/created-by: operator 11 | app.kubernetes.io/part-of: operator 12 | app.kubernetes.io/managed-by: kustomize 13 | name: retina-operator 14 | namespace: {{ .Values.namespace }} 15 | 16 | {{- end -}} 17 | -------------------------------------------------------------------------------- /deploy/standard/manifests/controller/helm/retina/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /deploy/standard/manifests/controller/helm/retina/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Installing retina service using helm: helm install retina ./deploy/standard/manifests/controller/helm/retina/ --namespace kube-system --dependency-update 2 | 2. Cleaning up/uninstalling/deleting retina and dependencies related: 3 | helm uninstall retina -n kube-system 4 | -------------------------------------------------------------------------------- /deploy/standard/manifests/controller/helm/retina/templates/networkobserver.yaml: -------------------------------------------------------------------------------- 1 | # apiVersion: networking.azure.com/v1alpha1 2 | # kind: ClusterObserver 3 | # metadata: 4 | # name: retina 5 | # namespace: retina 6 | # spec: 7 | # ignoreAllowed: true 8 | # exportList: 9 | # - otelAgent 10 | # observeList: 11 | # namespaceSelector: 12 | # matchLabels: 13 | # podSelector: 14 | # matchLabels: 15 | # direction: 16 | # ignoreList: 17 | # namespaceSelector: 18 | # matchLabels: 19 | # podSelector: 20 | # matchLabels: 21 | -------------------------------------------------------------------------------- /deploy/standard/manifests/controller/helm/retina/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "retina.fullname" . }} 5 | namespace: {{ .Values.namespace }} 6 | labels: 7 | k8s-app: {{ include "retina.name" . }} 8 | {{- include "retina.labels" . | nindent 4 }} 9 | app.kubernetes.io/component: networking 10 | spec: 11 | ports: 12 | - name: {{ .Values.service.name }} 13 | port: {{ .Values.service.port }} 14 | protocol: TCP 15 | targetPort: {{ .Values.service.targetPort }} 16 | selector: 17 | {{- include "retina.selectorLabels" . | nindent 4 }} 18 | app.kubernetes.io/component: workload 19 | -------------------------------------------------------------------------------- /deploy/standard/manifests/controller/helm/retina/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | {{- include "retina.labels" . | nindent 4 }} 6 | app.kubernetes.io/component: rbac 7 | k8s-app: {{ include "retina.name" . }} 8 | name: {{ .Values.serviceAccount.name }} 9 | namespace: {{ .Values.namespace }} 10 | -------------------------------------------------------------------------------- /deploy/standard/manifests/controller/helm/retina/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "retina.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "retina.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "retina.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /deploy/standard/prometheus/network-observability/create-cm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl delete cm ama-metrics-prometheus-config-node -n kube-system 4 | kubectl create configmap ama-metrics-prometheus-config-node --from-file=./deploy/standard/prometheus/cilium/prometheus-config -n kube-system 5 | k rollout restart ds ama-metrics-node -n kube-system 6 | -------------------------------------------------------------------------------- /deploy/standard/prometheus/network-observability/network-observability-svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: network-observability 5 | spec: 6 | ports: 7 | # control which ports we enable via which ports we define here 8 | - name: hubble 9 | protocol: TCP 10 | port: 9965 11 | targetPort: 9965 12 | - name: retina 13 | protocol: TCP 14 | port: 10093 15 | targetPort: 10093 16 | -------------------------------------------------------------------------------- /deploy/standard/prometheus/retina-windows/create-cm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl delete cm ama-metrics-prometheus-config-node -n kube-system 4 | 5 | kubectl create configmap ama-metrics-prometheus-config-node --from-file=./deploy/standard/prometheus/retina-windows/prometheus-config -n kube-system 6 | -------------------------------------------------------------------------------- /deploy/standard/prometheus/retina-windows/prometheus-config: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 60s 3 | scrape_configs: 4 | - job_name: "retina-pods" 5 | kubernetes_sd_configs: 6 | - role: pod 7 | relabel_configs: 8 | - source_labels: [__meta_kubernetes_pod_container_name] 9 | action: keep 10 | regex: retina(.*) 11 | - source_labels: 12 | [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] 13 | separator: ":" 14 | regex: ([^:]+)(?::\d+)? 15 | target_label: __address__ 16 | replacement: ${1}:${2} 17 | action: replace 18 | - source_labels: [__meta_kubernetes_pod_node_name] 19 | action: replace 20 | target_label: instance 21 | metric_relabel_configs: 22 | - source_labels: [__name__] 23 | action: keep 24 | regex: (.*) 25 | -------------------------------------------------------------------------------- /deploy/standard/prometheus/retina/create-cm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl create configmap ama-metrics-prometheus-config-node --from-file=./deploy/standard/prometheus/retina/prometheus-config -n kube-system 4 | -------------------------------------------------------------------------------- /deploy/standard/prometheus/retina/prometheus-config: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 60s 3 | scrape_configs: 4 | - job_name: "retina-pods" 5 | kubernetes_sd_configs: 6 | - role: pod 7 | relabel_configs: 8 | - source_labels: [__meta_kubernetes_pod_container_name] 9 | action: keep 10 | regex: retina(.*) 11 | - source_labels: 12 | [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] 13 | separator: ":" 14 | regex: ([^:]+)(?::\d+)? 15 | target_label: __address__ 16 | replacement: ${1}:${2} 17 | action: replace 18 | - source_labels: [__meta_kubernetes_pod_node_name] 19 | action: replace 20 | target_label: instance 21 | metric_relabel_configs: 22 | - source_labels: [__name__] 23 | action: keep 24 | regex: (.*) 25 | -------------------------------------------------------------------------------- /deploy/testutils/grafana/dashboards/simplify-grafana-overwrite_test.go: -------------------------------------------------------------------------------- 1 | //go:build dashboard && simplifydashboard 2 | 3 | package dashboard 4 | 5 | import ( 6 | "path/filepath" 7 | "testing" 8 | ) 9 | 10 | // TestOverwriteDashboards simplifies and overwrites Grafana dashboards in deploy folder variants 11 | func TestOverwriteDashboards(t *testing.T) { 12 | // get all json's in various generation deploly folders 13 | files, err := filepath.Glob("../../../grafana-dashboards/*.json") 14 | 15 | if err != nil { 16 | t.Fatal(err) 17 | } 18 | 19 | if len(files) != 6 { 20 | t.Fatal("Some JSON files are not found or new files have been addedd") 21 | } 22 | 23 | for _, file := range files { 24 | t.Logf("simplifying/overwriting dashboard: %s", file) 25 | 26 | sourcePath := file 27 | _ = SimplifyGrafana(sourcePath, true) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /deploy/testutils/grafana/dashboards/simplify-grafana_test.go: -------------------------------------------------------------------------------- 1 | //go:build dashboard && !simplifydashboard 2 | 3 | package dashboard 4 | 5 | import ( 6 | "path/filepath" 7 | "reflect" 8 | "testing" 9 | ) 10 | 11 | // TestDashboardsAreSimplified ensures that all dashboards are simplified 12 | func TestDashboardsAreSimplified(t *testing.T) { 13 | // get all json's in this folder 14 | files, err := filepath.Glob("../../../grafana-dashboards/*.json") 15 | 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | 20 | if len(files) != 6 { 21 | t.Fatal("Some JSON files are not found or new files have been addedd") 22 | } 23 | 24 | for _, file := range files { 25 | t.Logf("verifying that dashboard is simplified: %s", file) 26 | 27 | sourcePath := file 28 | simplified := SimplifyGrafana(sourcePath, false) 29 | original := ParseDashboard(sourcePath) 30 | 31 | if !reflect.DeepEqual(simplified, original) { 32 | t.Errorf("ERROR: dashboard has not been simplified. Please run: make simplify-dashboards") 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /docs/01-Introduction/img/Retina Arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/01-Introduction/img/Retina Arch.png -------------------------------------------------------------------------------- /docs/01-Introduction/img/control-plane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/01-Introduction/img/control-plane.png -------------------------------------------------------------------------------- /docs/01-Introduction/img/data-plane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/01-Introduction/img/data-plane.png -------------------------------------------------------------------------------- /docs/01-Introduction/img/hubble-control-plane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/01-Introduction/img/hubble-control-plane.png -------------------------------------------------------------------------------- /docs/01-Introduction/img/retina-components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/01-Introduction/img/retina-components.png -------------------------------------------------------------------------------- /docs/02-Installation/img/grafana-datasources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/02-Installation/img/grafana-datasources.png -------------------------------------------------------------------------------- /docs/02-Installation/img/grafana-import.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/02-Installation/img/grafana-import.png -------------------------------------------------------------------------------- /docs/02-Installation/img/grafana-kubernetes-networking-dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/02-Installation/img/grafana-kubernetes-networking-dash.png -------------------------------------------------------------------------------- /docs/02-Installation/img/grafana-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/02-Installation/img/grafana-login.png -------------------------------------------------------------------------------- /docs/02-Installation/img/grafana-retina-dns-dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/02-Installation/img/grafana-retina-dns-dash.png -------------------------------------------------------------------------------- /docs/02-Installation/img/prometheus-retina-targets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/02-Installation/img/prometheus-retina-targets.png -------------------------------------------------------------------------------- /docs/03-Metrics/annotations.md: -------------------------------------------------------------------------------- 1 | # Annotations 2 | 3 | Annotations let you specify which Pods to observe (create metrics for). 4 | To configure this, specify `enableAnnotations=true` in Retina's [helm installation](../02-Installation/01-Setup.md) or [ConfigMap](../02-Installation/03-Config.md). 5 | 6 | You can then add the annotation `retina.sh: observe` to either: 7 | 8 | - individual Pods 9 | - Namespaces (to observe all the Pods in the namespace). 10 | 11 | An exception: currently all Pods in `kube-system` are always monitored. 12 | 13 | **Note**: If you enable Annotations, you cannot use the `MetricsConfiguration` CRD to specify which Pods to observe. 14 | -------------------------------------------------------------------------------- /docs/03-Metrics/configuration.md: -------------------------------------------------------------------------------- 1 | # Metrics Configuration 2 | 3 | You can enable/disable metrics by including/omitting their Plugin from `enabledPlugins` in either Retina's [helm installation](../02-Installation/01-Setup.md) or [ConfigMap](../02-Installation/03-Config.md). 4 | 5 | Via [MetricsConfiguration CRD](../05-Concepts/CRDs/MetricsConfiguration.md), you can further customize the following for your enabled plugins: 6 | 7 | - Which metrics to include 8 | - Which metadata to include for a metric. 9 | 10 | **Note**: If you enable [Annotations](./annotations.md), you cannot use the `MetricsConfiguration` CRD to specify which Pods to observe. 11 | -------------------------------------------------------------------------------- /docs/03-Metrics/plugins/Linux/packetforward.md: -------------------------------------------------------------------------------- 1 | # `packetforward` 2 | 3 | Counts number of packets/bytes passing through the `eth0` interface of a Node, along with the direction of the packets. 4 | 5 | ## Capabilities 6 | 7 | The `packetforward` plugin requires the `CAP_BPF` capability. 8 | 9 | ## Architecture 10 | 11 | `packetforward` uses an eBPF socket filter program on the host's primary interface to capture packets and generate basic metrics from the captured data. 12 | 13 | ### Code locations 14 | 15 | - Plugin and eBPF code: *pkg/plugin/packetforward/* 16 | 17 | ## Metrics 18 | 19 | See metrics for [Basic Mode](../../modes/basic.md#plugin-packetforward-linux) (Advanced modes have identical metrics). 20 | 21 | :::note 22 | 23 | `adv_forward_count` and `adv_forward_bytes` metrics are NOT associated with `packetforward` plugin despite similarities in name. 24 | These metrics are associated with [`packetparser`](./packetparser.md). 25 | 26 | ::: 27 | -------------------------------------------------------------------------------- /docs/03-Metrics/plugins/Linux/tcpretrans.md: -------------------------------------------------------------------------------- 1 | # `tcpretrans` 2 | 3 | Measures retransmitted TCP packets. 4 | 5 | ## Capabilities 6 | 7 | The `tcpretrans` plugin requires the `CAP_SYS_ADMIN` capability. 8 | 9 | ## Architecture 10 | 11 | The plugin utilizes eBPF to gather data. 12 | The plugin does not generate Basic metrics. 13 | In Advanced mode (see [Metric Modes](../../modes/modes.md)), the plugin turns an eBPF result into an enriched `Flow` (adding Pod information based on IP), then sends the `Flow` to an external channel so that a tcpretrans module can create Pod-Level metrics. 14 | 15 | ### Code locations 16 | 17 | - Plugin and eBPF code: *pkg/plugin/tcpretrans/* 18 | - Module for extra Advanced metrics: *pkg/module/metrics/tcpretrans.go* 19 | 20 | ## Metrics 21 | 22 | See metrics for [Advanced Mode](../../modes/advanced.md#plugin-tcpretrans-linux). 23 | -------------------------------------------------------------------------------- /docs/03-Metrics/plugins/Windows/hnsstats.md: -------------------------------------------------------------------------------- 1 | # `hnsstats` 2 | 3 | Gathers TCP statistics and counts number of packets/bytes forwarded or dropped in HNS and VFP. 4 | 5 | ## Architecture 6 | 7 | Interfaces with a Windows Node's HNS (Host Networking System) and VFP (Virtual Filtering Platform). 8 | 9 | ### Code Locations 10 | 11 | - Plugin code interfacing with HNS/VFP: *pkg/plugin/windows/hnsstats* 12 | 13 | ## Metrics 14 | 15 | See metrics for [Basic Mode](../../modes/basic.md#plugin-hnsstats-windows) (Advanced modes have identical metrics). 16 | -------------------------------------------------------------------------------- /docs/04-Captures/img/capture-architecture-with-operator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/04-Captures/img/capture-architecture-with-operator.png -------------------------------------------------------------------------------- /docs/04-Captures/img/capture-architecture-without-operator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/04-Captures/img/capture-architecture-without-operator.png -------------------------------------------------------------------------------- /docs/04-Captures/img/capture-managed-storage-account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/04-Captures/img/capture-managed-storage-account.png -------------------------------------------------------------------------------- /docs/04-Captures/img/retina-release.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/04-Captures/img/retina-release.png -------------------------------------------------------------------------------- /docs/06-Troubleshooting/imgs/prom-retina-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/06-Troubleshooting/imgs/prom-retina-config.png -------------------------------------------------------------------------------- /docs/06-Troubleshooting/imgs/prom-retina-service-discovery1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/06-Troubleshooting/imgs/prom-retina-service-discovery1.png -------------------------------------------------------------------------------- /docs/06-Troubleshooting/imgs/prom-retina-service-discovery2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/06-Troubleshooting/imgs/prom-retina-service-discovery2.png -------------------------------------------------------------------------------- /docs/06-Troubleshooting/imgs/prometheus-retina-targets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/06-Troubleshooting/imgs/prometheus-retina-targets.png -------------------------------------------------------------------------------- /docs/07-Integrations/img/hubble-cli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/07-Integrations/img/hubble-cli.png -------------------------------------------------------------------------------- /docs/07-Integrations/img/hubble-ui-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/07-Integrations/img/hubble-ui-home.png -------------------------------------------------------------------------------- /docs/07-Integrations/img/hubble-ui-service-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/07-Integrations/img/hubble-ui-service-map.png -------------------------------------------------------------------------------- /docs/07-Integrations/img/wireshark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/docs/07-Integrations/img/wireshark.png -------------------------------------------------------------------------------- /get-certs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | set -x 5 | 6 | # Directory where certificates will be stored 7 | CERT_DIR="$(pwd)/.certs" 8 | mkdir -p "$CERT_DIR" 9 | 10 | declare -A CERT_FILES=( 11 | ["tls.crt"]="tls-client-cert-file" 12 | ["tls.key"]="tls-client-key-file" 13 | ["ca.crt"]="tls-ca-cert-files" 14 | ) 15 | 16 | for FILE in "${!CERT_FILES[@]}"; do 17 | KEY="${CERT_FILES[$FILE]}" 18 | JSONPATH="{.data['${FILE//./\\.}']}" 19 | 20 | # Retrieve the secret and decode it 21 | kubectl get secret hubble-relay-client-certs -n kube-system \ 22 | -o jsonpath="${JSONPATH}" | \ 23 | base64 -d > "$CERT_DIR/$FILE" 24 | 25 | # Set the appropriate hubble CLI config 26 | hubble config set "$KEY" "$CERT_DIR/$FILE" 27 | done 28 | 29 | hubble config set tls true 30 | hubble config set tls-server-name instance.hubble-relay.cilium.io 31 | -------------------------------------------------------------------------------- /hack/tools/kapinger/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | -------------------------------------------------------------------------------- /hack/tools/kapinger/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2 AS builder 2 | 3 | WORKDIR /build 4 | ADD . . 5 | RUN go mod download 6 | 7 | # Build for Linux 8 | RUN CGO_ENABLED=0 GOOS=linux go build -o kapinger . 9 | 10 | # Build for Windows 11 | RUN CGO_ENABLED=0 GOOS=windows go build -o kapinger.exe . 12 | 13 | # Build for ARM64 Linux 14 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o kapinger-arm64 . 15 | 16 | FROM --platform=linux/amd64 scratch AS linux-amd64 17 | WORKDIR /app 18 | COPY --from=builder /build/kapinger . 19 | CMD ["./kapinger"] 20 | 21 | FROM --platform=windows/amd64 mcr.microsoft.com/windows/servercore:ltsc2022 AS windows-amd64 22 | WORKDIR /app 23 | COPY --from=builder /build/kapinger.exe . 24 | ENTRYPOINT [ "cmd.exe" ] 25 | CMD [ "/c", "kapinger.exe" ] 26 | 27 | FROM --platform=linux/arm64 scratch AS linux-arm64 28 | WORKDIR /app 29 | COPY --from=builder /build/kapinger-arm64 . 30 | CMD ["./kapinger-arm64"] 31 | -------------------------------------------------------------------------------- /hack/tools/kapinger/clients/client.go: -------------------------------------------------------------------------------- 1 | package clients 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Client interface { 8 | MakeRequests(ctx context.Context) error 9 | } 10 | -------------------------------------------------------------------------------- /hack/tools/kapinger/servers/server.go: -------------------------------------------------------------------------------- 1 | package servers 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | "github.com/microsoft/retina/hack/tools/kapinger/config" 8 | ) 9 | 10 | type Server interface { 11 | Start(ctx context.Context) error 12 | } 13 | 14 | type Kapinger struct { 15 | servers []Server 16 | } 17 | 18 | func (k *Kapinger) Start(ctx context.Context) { 19 | for i := range k.servers { 20 | go func(i int) { 21 | err := k.servers[i].Start(ctx) 22 | if err != nil { 23 | log.Printf("Error starting server: %s\n", err) 24 | } 25 | }(i) 26 | } 27 | <-ctx.Done() 28 | } 29 | 30 | func StartAll(ctx context.Context, config *config.KapingerConfig) { 31 | k := &Kapinger{ 32 | servers: []Server{ 33 | NewKapingerTCPServer(config.TCPPort), 34 | NewKapingerUDPServer(config.UDPPort), 35 | NewKapingerHTTPServer(config.HTTPPort), 36 | }, 37 | } 38 | 39 | // cancel 40 | k.Start(ctx) 41 | } 42 | -------------------------------------------------------------------------------- /hack/tools/kapinger/servers/util.go: -------------------------------------------------------------------------------- 1 | package servers 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | func getResponse(addressString, protocol string) []byte { 9 | podname := os.Getenv("POD_NAME") 10 | return []byte(fmt.Sprintf("connected to: %s via %s, connected from: %v", podname, protocol, addressString)) 11 | } 12 | -------------------------------------------------------------------------------- /hack/tools/toolbox/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | -------------------------------------------------------------------------------- /hack/tools/toolbox/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/microsoft/retina/hack/tools/toolbox 2 | 3 | go 1.24.2 4 | 5 | replace github.com/microsoft/retina/hack/tools/kapinger => ../kapinger 6 | 7 | require github.com/microsoft/retina/hack/tools/kapinger v0.0.0-20241101210114-ecdabdbf715f 8 | -------------------------------------------------------------------------------- /hack/tools/toolbox/go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/hack/tools/toolbox/go.sum -------------------------------------------------------------------------------- /hack/tools/toolbox/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/microsoft/retina/hack/tools/kapinger/config" 7 | "github.com/microsoft/retina/hack/tools/kapinger/servers" 8 | ) 9 | 10 | func main() { 11 | cfg := config.LoadConfigFromEnv() 12 | ctx := context.Background() 13 | servers.StartAll(ctx, cfg) 14 | } 15 | -------------------------------------------------------------------------------- /internal/buildinfo/buildinfo.go: -------------------------------------------------------------------------------- 1 | package buildinfo 2 | 3 | // These variables will be populate by the Go compiler via 4 | // the -ldflags, which insert dynamic information 5 | // into the binary at build time 6 | var ( 7 | // ApplicationInsightsID is the instrumentation key for Azure Application Insights 8 | // It is set during the build process using the -ldflags flag 9 | // If it is set, the application will send telemetry to the corresponding Application Insights resource. 10 | ApplicationInsightsID string 11 | Version string 12 | ) 13 | -------------------------------------------------------------------------------- /internal/ktime/ktime.go: -------------------------------------------------------------------------------- 1 | package ktime 2 | 3 | // MonotonicOffset is the calculated skew between the kernel's 4 | // monotonic timer and UTC. 5 | // 6 | // If clock readings were instantaneous, this would mean that 7 | // MonotonicTimer - MonotonicOFfset = the UTC Boot Time, but 8 | // that is idealized and there will be some small errror. 9 | var MonotonicOffset = calculateMonotonicOffset() 10 | -------------------------------------------------------------------------------- /internal/ktime/ktime_other.go: -------------------------------------------------------------------------------- 1 | //go:build !unix 2 | 3 | package ktime 4 | 5 | import "time" 6 | 7 | func calculateMonotonicOffset() time.Duration { 8 | return 0 * time.Nanosecond 9 | } 10 | -------------------------------------------------------------------------------- /internal/ktime/ktime_unix.go: -------------------------------------------------------------------------------- 1 | //go:build unix 2 | 3 | package ktime 4 | 5 | import ( 6 | "time" 7 | 8 | "golang.org/x/sys/unix" 9 | ) 10 | 11 | // calculateMonotonicOffset tries to determine the offset of the kernel's 12 | // monotonic clock from UTC so that measurements from eBPF using the 13 | // monotonic clock timestamp may be adjusted to wall-time. 14 | // 15 | // These instructions do not execute instantaneously so it will always be 16 | // impossible to sample both clocks at exactly the same time. 17 | // This means that for any single process there will be constant error in 18 | // the accuracy of this measurement despite the nanosecond-level precision 19 | // of the individual clocks. 20 | func calculateMonotonicOffset() time.Duration { 21 | mono := &unix.Timespec{} 22 | now := time.Now() 23 | _ = unix.ClockGettime(unix.CLOCK_BOOTTIME, mono) 24 | return time.Duration(now.UnixNano() - unix.TimespecToNsec(*mono)) 25 | } 26 | -------------------------------------------------------------------------------- /operator/cilium-crds/config/config_linux.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/cilium/hive/cell" 5 | "github.com/spf13/pflag" 6 | 7 | sharedconfig "github.com/microsoft/retina/pkg/shared/config" 8 | ) 9 | 10 | type Config struct { 11 | EnableTelemetry bool 12 | LeaderElection bool 13 | } 14 | 15 | func (c Config) Flags(flags *pflag.FlagSet) { 16 | flags.Bool("enable-telemetry", c.EnableTelemetry, "enable telemetry (send logs and metrics to a remote server)") 17 | flags.Bool("leader-election", c.LeaderElection, "Enable leader election for operator. Ensures there is only one active operator Pod") 18 | } 19 | 20 | var ( 21 | DefaultConfig = Config{ 22 | EnableTelemetry: false, 23 | LeaderElection: false, 24 | } 25 | 26 | Cell = cell.Module( 27 | "operator-config", 28 | "Operator Config", 29 | cell.Config(DefaultConfig), 30 | sharedconfig.Cell, 31 | ) 32 | ) 33 | -------------------------------------------------------------------------------- /operator/cilium-crds/k8s/fakeresource.go: -------------------------------------------------------------------------------- 1 | package k8s 2 | 3 | import ( 4 | "context" 5 | 6 | k8sRuntime "k8s.io/apimachinery/pkg/runtime" 7 | 8 | "github.com/cilium/cilium/pkg/k8s/resource" 9 | ) 10 | 11 | type fakeresource[T k8sRuntime.Object] struct { 12 | } 13 | 14 | func (f *fakeresource[T]) Events(ctx context.Context, opts ...resource.EventsOpt) <-chan resource.Event[T] { 15 | return make(<-chan resource.Event[T]) 16 | } 17 | 18 | func (f *fakeresource[T]) Store(ctx context.Context) (resource.Store[T], error) { 19 | return nil, nil 20 | } 21 | 22 | func (f *fakeresource[T]) Observe(ctx context.Context, next func(resource.Event[T]), complete func(error)) { 23 | } 24 | -------------------------------------------------------------------------------- /operator/cmd/cilium-crds/flags_provider.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Authors of Cilium and Retina 3 | 4 | // NOTE: we could reference this file Cilium's code, but it is a small file. 5 | // Referencing Cilium's code requires importing dependencies 6 | // we don't need from their operator, which has BGP dependencies for instance. 7 | // This is currently resulting in an error in go mod tidy: 8 | // module go.universe.tf/metallb@latest found (v0.13.12), but does not contain package go.universe.tf/metallb/pkg/speaker 9 | 10 | package ciliumcrds 11 | 12 | import ( 13 | "github.com/spf13/cobra" 14 | "github.com/spf13/viper" 15 | ) 16 | 17 | type ProviderFlagsHooks interface { 18 | RegisterProviderFlag(cmd *cobra.Command, vp *viper.Viper) 19 | } 20 | -------------------------------------------------------------------------------- /operator/cmd/cilium-crds/metrics.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Authors of Cilium and Retina 3 | 4 | // NOTE: changed to say networkobservability_operator 5 | 6 | package ciliumcrds 7 | 8 | import ( 9 | "github.com/spf13/cobra" 10 | ) 11 | 12 | const RetinaOperatorMetricsNamespace = "networkobservability_operator" 13 | 14 | // MetricsCmd represents the metrics command for the operator. 15 | var MetricsCmd = &cobra.Command{ 16 | Use: "metrics", 17 | Short: "Access metric status of the operator", 18 | } 19 | -------------------------------------------------------------------------------- /operator/config/testwith/config-small-telemetry-interval.yaml: -------------------------------------------------------------------------------- 1 | apiServer: 2 | host: "0.0.0.0" 3 | port: 10093 4 | installCRDs: true 5 | enableTelemetry: true 6 | logLevel: info 7 | enableRetinaEndpoint: true 8 | remoteContext: true 9 | telemetryInterval: "10s" 10 | -------------------------------------------------------------------------------- /operator/config/testwith/config-without-telemetry-interval.yaml: -------------------------------------------------------------------------------- 1 | apiServer: 2 | host: "0.0.0.0" 3 | port: 10093 4 | installCRDs: true 5 | enableTelemetry: true 6 | logLevel: info 7 | enableRetinaEndpoint: true 8 | remoteContext: true 9 | -------------------------------------------------------------------------------- /operator/config/testwith/config.yaml: -------------------------------------------------------------------------------- 1 | apiServer: 2 | host: "0.0.0.0" 3 | port: 10093 4 | installCRDs: true 5 | enableTelemetry: true 6 | logLevel: info 7 | enableRetinaEndpoint: true 8 | remoteContext: true 9 | telemetryInterval: "15m" 10 | -------------------------------------------------------------------------------- /operator/main.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package main 5 | 6 | import "github.com/microsoft/retina/operator/cmd" 7 | 8 | func main() { 9 | cmd.Execute() 10 | } 11 | -------------------------------------------------------------------------------- /pkg/capture/constants/windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package constants 5 | 6 | // ContainerSandboxMountPointEnvKey provides the absolute host path to the container volume. 7 | const ContainerSandboxMountPointEnvKey = "CONTAINER_SANDBOX_MOUNT_POINT" 8 | -------------------------------------------------------------------------------- /pkg/capture/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | // Package capture contains functions related to handling Retina/Capture. 5 | package capture // import "github.com/microsoft/retina/pkg/capture" 6 | -------------------------------------------------------------------------------- /pkg/capture/error.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package capture 5 | 6 | import "fmt" 7 | 8 | var _ error = SecretNotFoundError{} 9 | 10 | type SecretNotFoundError struct { 11 | SecretName string 12 | Namespace string 13 | } 14 | 15 | func (err SecretNotFoundError) Error() string { 16 | return fmt.Sprintf("secret of Capture is not found when blobupload is enabled, secretName: %s/%s", err.SecretName, err.Namespace) 17 | } 18 | 19 | // define a error struct for capture job number limit 20 | var _ error = CaptureJobNumExceedLimitError{} 21 | 22 | type CaptureJobNumExceedLimitError struct { 23 | CurrentNum int 24 | Limit int 25 | } 26 | 27 | func (err CaptureJobNumExceedLimitError) Error() string { 28 | return fmt.Sprintf("the number of capture jobs %d exceeds the limit %d", err.CurrentNum, err.Limit) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/capture/file/capture_filename.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type CaptureFilename struct { 8 | CaptureName string 9 | NodeHostname string 10 | StartTimestamp *Timestamp 11 | } 12 | 13 | func (cf *CaptureFilename) String() string { 14 | uniqueName := fmt.Sprintf("%s-%s-%s", cf.CaptureName, cf.NodeHostname, cf.StartTimestamp) 15 | return uniqueName 16 | } 17 | -------------------------------------------------------------------------------- /pkg/capture/file/timestamp.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/pkg/errors" 7 | ) 8 | 9 | type Timestamp struct { 10 | time.Time 11 | } 12 | 13 | const captureFileNameTimestampFormat string = "20060102150405UTC" 14 | 15 | func Now() Timestamp { 16 | return Timestamp{Time: time.Now().UTC().Truncate(time.Second)} 17 | } 18 | 19 | func (timestamp *Timestamp) String() string { 20 | return timestamp.Time.Format(captureFileNameTimestampFormat) 21 | } 22 | 23 | func StringToTimestamp(timestamp string) (*Timestamp, error) { 24 | parsedTime, err := time.Parse(captureFileNameTimestampFormat, timestamp) 25 | if err != nil { 26 | return nil, errors.Wrap(err, "failed to create timestamp from string") 27 | } 28 | return &Timestamp{parsedTime}, nil 29 | } 30 | -------------------------------------------------------------------------------- /pkg/capture/outputlocation/managed/doc.go: -------------------------------------------------------------------------------- 1 | // managed package provides the functionality to manage the output locations for the Capture. 2 | package managed 3 | -------------------------------------------------------------------------------- /pkg/capture/outputlocation/output.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package outputlocation 5 | 6 | import "context" 7 | 8 | type Location interface { 9 | // Name returns the name of the output location. 10 | Name() string 11 | // Enabled checks whether a output location is enabled. 12 | Enabled() bool 13 | // Output outputs source file to the location specified by the users. 14 | Output(ctx context.Context, srcFilePath string) error 15 | } 16 | -------------------------------------------------------------------------------- /pkg/capture/provider/interface.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package provider 5 | 6 | import ( 7 | "context" 8 | 9 | "github.com/microsoft/retina/pkg/capture/file" 10 | ) 11 | 12 | //go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=interface.go -destination=mock_network_capture.go -package=provider Interface 13 | type NetworkCaptureProviderInterface interface { 14 | // Setup prepares the provider with folder to store network capture for temporary. 15 | Setup(filename file.CaptureFilename) (string, error) 16 | // CaptureNetworkPacket capture network traffic per user input and store the captured network packets in local directory. 17 | CaptureNetworkPacket(ctx context.Context, filter string, duration, maxSize int) error 18 | // CollectMetadata collects network metadata and store network metadata info in local directory. 19 | CollectMetadata() error 20 | // Cleanup removes created resources. 21 | Cleanup() error 22 | } 23 | -------------------------------------------------------------------------------- /pkg/capture/test_helper.go: -------------------------------------------------------------------------------- 1 | package capture 2 | 3 | import ( 4 | "context" 5 | "os/signal" 6 | "syscall" 7 | "testing" 8 | ) 9 | 10 | func TestContext(t *testing.T) (context.Context, context.CancelFunc) { 11 | ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM) 12 | 13 | deadline, ok := t.Deadline() 14 | if ok { 15 | return context.WithDeadline(ctx, deadline) 16 | } 17 | 18 | return ctx, cancel 19 | } 20 | -------------------------------------------------------------------------------- /pkg/capture/utils/label.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package utils 5 | 6 | import ( 7 | captureConstants "github.com/microsoft/retina/pkg/capture/constants" 8 | "github.com/microsoft/retina/pkg/label" 9 | ) 10 | 11 | func GetSerectLabelsFromCaptureName(captureName string) map[string]string { 12 | return map[string]string{ 13 | label.AppLabel: captureConstants.CaptureAppname, 14 | label.CaptureNameLabel: captureName, 15 | } 16 | } 17 | 18 | func GetJobLabelsFromCaptureName(captureName string) map[string]string { 19 | return map[string]string{ 20 | label.AppLabel: captureConstants.CaptureAppname, 21 | label.CaptureNameLabel: captureName, 22 | } 23 | } 24 | 25 | func GetContainerLabelsFromCaptureName(captureName string) map[string]string { 26 | return map[string]string{ 27 | label.AppLabel: captureConstants.CaptureAppname, 28 | label.CaptureNameLabel: captureName, 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /pkg/common/apiretry/apiretry.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | // package apiretry provides the retry logic for API calls. 5 | package apiretry 6 | 7 | import ( 8 | "time" 9 | 10 | apierrors "k8s.io/apimachinery/pkg/api/errors" 11 | "k8s.io/client-go/util/retry" 12 | ) 13 | 14 | // Do will retry the do func only when the error is transient. 15 | func Do(do func() error) error { 16 | backOffPeriod := retry.DefaultBackoff 17 | backOffPeriod.Cap = time.Second * 1 18 | 19 | return retry.OnError(backOffPeriod, func(err error) bool { 20 | return retriable(err) 21 | }, do) 22 | } 23 | 24 | func retriable(err error) bool { 25 | if apierrors.IsTimeout(err) || 26 | apierrors.IsServerTimeout(err) || 27 | apierrors.IsTooManyRequests(err) { 28 | return true 29 | } 30 | return false 31 | } 32 | -------------------------------------------------------------------------------- /pkg/common/node.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package common 4 | 5 | import "net" 6 | 7 | func NewRetinaNode(name string, ip net.IP) *RetinaNode { 8 | return &RetinaNode{ 9 | name: name, 10 | ip: ip, 11 | } 12 | } 13 | 14 | func (n *RetinaNode) DeepCopy() interface{} { 15 | newN := &RetinaNode{ 16 | name: n.name, 17 | } 18 | 19 | if n.ip != nil { 20 | newN.ip = make(net.IP, len(n.ip)) 21 | copy(newN.ip, n.ip) 22 | } 23 | 24 | return newN 25 | } 26 | 27 | func (n *RetinaNode) IPString() string { 28 | return n.ip.String() 29 | } 30 | 31 | func (n *RetinaNode) Name() string { 32 | return n.name 33 | } 34 | -------------------------------------------------------------------------------- /pkg/common/pubsubtopics.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package common 4 | 5 | import "github.com/microsoft/retina/pkg/pubsub" 6 | 7 | const ( 8 | // PubSubPods topic 9 | PubSubPods pubsub.PubSubTopic = "pods" 10 | // PubSubEndpoints topic 11 | PubSubEndpoints pubsub.PubSubTopic = "endpoints" 12 | // PubSubSvc topic 13 | PubSubSvc pubsub.PubSubTopic = "svc" 14 | // PubSubNode topic 15 | PubSubNode pubsub.PubSubTopic = "node" 16 | // PubSubVeth topic 17 | PubSubVeth pubsub.PubSubTopic = "veth" 18 | // PubSubNamespace topic 19 | PubSubNamespace pubsub.PubSubTopic = "namespace" 20 | // PubSubFilterRule topic 21 | PubSubFilterRule pubsub.PubSubTopic = "filterrule" 22 | // PubSubAPIServer topic 23 | PubSubAPIServer pubsub.PubSubTopic = "apiserver" 24 | ) 25 | -------------------------------------------------------------------------------- /pkg/config/testwith/config-mock.yaml: -------------------------------------------------------------------------------- 1 | apiServer: 2 | host: "0.0.0.0" 3 | port: 10093 4 | # Supported - debug, info, error, warn, panic, fatal. 5 | logLevel: info 6 | enabledPlugin: ["mockplugin"] 7 | # Interval, in seconds, to scrape/publish metrics. 8 | metricsIntervalDuration: "10s" 9 | # used to export telemetry to AppInsights 10 | telemetryEnabled: true 11 | -------------------------------------------------------------------------------- /pkg/config/testwith/config-small-telemetry-interval.yaml: -------------------------------------------------------------------------------- 1 | apiServer: 2 | host: "0.0.0.0" 3 | port: 10093 4 | # Supported - debug, info, error, warn, panic, fatal. 5 | logLevel: info 6 | enabledPlugin: ["dropreason", "packetforward", "linuxutil"] 7 | # Interval, in seconds, to scrape/publish metrics. 8 | metricsIntervalDuration: "10s" 9 | # used to export telemetry to AppInsights 10 | telemetryEnabled: true 11 | dataAggregationLevel: "low" 12 | telemetryInterval: "10s" 13 | -------------------------------------------------------------------------------- /pkg/config/testwith/config-win.yaml: -------------------------------------------------------------------------------- 1 | apiServer: 2 | host: "0.0.0.0" 3 | port: 10093 4 | # Supported - debug, info, error, warn, panic, fatal. 5 | logLevel: info 6 | enabledPlugin: ["hnsstats"] 7 | # Interval, in seconds, to scrape/publish metrics. 8 | metricsIntervalDuration: "10s" 9 | # used to export telemetry to AppInsights 10 | telemetryEnabled: true 11 | -------------------------------------------------------------------------------- /pkg/config/testwith/config-without-telemetry-interval.yaml: -------------------------------------------------------------------------------- 1 | apiServer: 2 | host: "0.0.0.0" 3 | port: 10093 4 | # Supported - debug, info, error, warn, panic, fatal. 5 | logLevel: info 6 | enabledPlugin: ["dropreason", "packetforward", "linuxutil"] 7 | # Interval, in seconds, to scrape/publish metrics. 8 | metricsIntervalDuration: "10s" 9 | # used to export telemetry to AppInsights 10 | telemetryEnabled: true 11 | dataAggregationLevel: "low" 12 | -------------------------------------------------------------------------------- /pkg/config/testwith/config.yaml: -------------------------------------------------------------------------------- 1 | apiServer: 2 | host: "0.0.0.0" 3 | port: 10093 4 | # Supported - debug, info, error, warn, panic, fatal. 5 | logLevel: info 6 | enabledPlugin: ["dropreason", "packetforward", "linuxutil"] 7 | # Interval, in seconds, to scrape/publish metrics. 8 | metricsIntervalDuration: "10s" 9 | # used to export telemetry to AppInsights 10 | telemetryEnabled: true 11 | dataAggregationLevel: "low" 12 | telemetryInterval: "15m" 13 | -------------------------------------------------------------------------------- /pkg/controllers/operator/capture/doc.go: -------------------------------------------------------------------------------- 1 | // package capture features the retina capture controller. 2 | package capture 3 | -------------------------------------------------------------------------------- /pkg/controllers/operator/cilium-crds/cache/types.go: -------------------------------------------------------------------------------- 1 | package cache 2 | 3 | import ( 4 | slim_corev1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/api/core/v1" 5 | 6 | "github.com/cilium/cilium/pkg/k8s/resource" 7 | ) 8 | 9 | type PodCacheObject struct { 10 | Key resource.Key 11 | Pod *slim_corev1.Pod 12 | } 13 | -------------------------------------------------------------------------------- /pkg/controllers/operator/cilium-crds/endpoint/cell_linux.go: -------------------------------------------------------------------------------- 1 | package endpointcontroller 2 | 3 | import "github.com/cilium/hive/cell" 4 | 5 | var Cell = cell.Module( 6 | "endpointcontroller", 7 | "controller for cilium endpoint and identity creation and updates", 8 | cell.Invoke(registerEndpointController), 9 | ) 10 | -------------------------------------------------------------------------------- /pkg/enricher/types.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package enricher 4 | 5 | import ( 6 | v1 "github.com/cilium/cilium/pkg/hubble/api/v1" 7 | "github.com/cilium/cilium/pkg/hubble/container" 8 | ) 9 | 10 | //go:generate go run go.uber.org/mock/mockgen@v0.4.0 -destination=mock_enricherinterface.go -copyright_file=../lib/ignore_headers.txt -package=enricher github.com/microsoft/retina/pkg/enricher EnricherInterface 11 | 12 | type EnricherInterface interface { 13 | Run() 14 | Write(ev *v1.Event) 15 | ExportReader() *container.RingReader 16 | } 17 | -------------------------------------------------------------------------------- /pkg/hubble/common/decoder.go: -------------------------------------------------------------------------------- 1 | package common 2 | -------------------------------------------------------------------------------- /pkg/label/k8s.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package label 5 | 6 | const ( 7 | 8 | // LabelPrefix is the prefix for all Retina owned labels. 9 | LabelPrefix = "retina.sh" 10 | 11 | // AppLabel indicates the Retina-owned application 12 | AppLabel = LabelPrefix + "/app" 13 | 14 | CaptureNameLabel = "capture-name" 15 | ) 16 | -------------------------------------------------------------------------------- /pkg/lib/ignore_headers.txt: -------------------------------------------------------------------------------- 1 | autogenerated 2 | 3 | Copyright (c) Microsoft Corporation. 4 | Licensed under the MIT license. 5 | -------------------------------------------------------------------------------- /pkg/loader/compile.go: -------------------------------------------------------------------------------- 1 | package loader 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "os/exec" 7 | 8 | "github.com/microsoft/retina/pkg/log" 9 | "go.uber.org/zap" 10 | ) 11 | 12 | var compiler string = "clang" 13 | 14 | func runCmd(cmd *exec.Cmd) error { 15 | l := log.Logger().Named(string("run-command")) 16 | 17 | var out, stderr bytes.Buffer 18 | 19 | cmd.Stdout = &out 20 | cmd.Stderr = &stderr 21 | 22 | l.Debug("Running", zap.String("command", cmd.String())) 23 | 24 | err := cmd.Run() 25 | if err != nil { 26 | l.Debug("Error running command", zap.String("command", cmd.String()), zap.String("stderr", stderr.String()), zap.Error(err)) 27 | return err 28 | } 29 | l.Debug("Output running command", zap.String("command", cmd.String()), zap.String("stdout", out.String())) 30 | return nil 31 | } 32 | 33 | func CompileEbpf(ctx context.Context, args ...string) error { 34 | cmd := exec.CommandContext(ctx, compiler, args...) 35 | err := runCmd(cmd) 36 | if err != nil { 37 | return err 38 | } 39 | return nil 40 | } 41 | -------------------------------------------------------------------------------- /pkg/loader/generate.go: -------------------------------------------------------------------------------- 1 | package loader 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | func WriteFile(ctx context.Context, destFile, text string) error { 10 | tmpFile := fmt.Sprintf("%s.tmp", destFile) 11 | outputFile, err := os.Create(tmpFile) 12 | if err != nil { 13 | return err 14 | } 15 | defer outputFile.Close() 16 | 17 | _, err = outputFile.WriteString(text) 18 | if err != nil { 19 | return err 20 | } 21 | 22 | err = os.Rename(tmpFile, destFile) 23 | if err != nil { 24 | return err 25 | } 26 | return nil 27 | } 28 | -------------------------------------------------------------------------------- /pkg/managers/filtermanager/manager_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package filtermanager 5 | 6 | import ( 7 | "net" 8 | ) 9 | 10 | // FilterManager is a no-op implementation of the filter manager for Windows. 11 | 12 | type FilterManager struct{} 13 | 14 | func Init(_ int) (*FilterManager, error) { 15 | return nil, nil 16 | } 17 | 18 | func (f *FilterManager) AddIPs(_ []net.IP, _ Requestor, _ RequestMetadata) error { 19 | return nil 20 | } 21 | 22 | func (f *FilterManager) DeleteIPs(_ []net.IP, _ Requestor, _ RequestMetadata) error { 23 | return nil 24 | } 25 | 26 | func (f *FilterManager) HasIP(_ net.IP) bool { 27 | return false 28 | } 29 | 30 | func (f *FilterManager) Reset() error { 31 | return nil 32 | } 33 | 34 | func (f *FilterManager) Stop() error { 35 | return nil 36 | } 37 | -------------------------------------------------------------------------------- /pkg/managers/watchermanager/types.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package watchermanager 5 | 6 | import ( 7 | "context" 8 | "sync" 9 | "time" 10 | 11 | "github.com/microsoft/retina/pkg/log" 12 | ) 13 | 14 | //go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=types.go -destination=mocks/mock_types.go -package=mocks . 15 | type IWatcher interface { 16 | // Init, Stop, and Refresh should only be called by watchermanager. 17 | Init(ctx context.Context) error 18 | Stop(ctx context.Context) error 19 | Refresh(ctx context.Context) error 20 | } 21 | 22 | type IWatcherManager interface { 23 | Start(ctx context.Context) error 24 | Stop(ctx context.Context) error 25 | } 26 | 27 | type WatcherManager struct { 28 | Watchers []IWatcher 29 | l *log.ZapLogger 30 | refreshRate time.Duration 31 | cancel context.CancelFunc 32 | wg sync.WaitGroup 33 | } 34 | -------------------------------------------------------------------------------- /pkg/metrics/interfaces.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package metrics 4 | 5 | import ( 6 | "github.com/prometheus/client_golang/prometheus" 7 | dto "github.com/prometheus/client_model/go" 8 | ) 9 | 10 | //go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=interfaces.go -destination=mock_types.go -package=metrics 11 | 12 | type CounterVec interface { 13 | WithLabelValues(lvs ...string) prometheus.Counter 14 | GetMetricWithLabelValues(lvs ...string) (prometheus.Counter, error) 15 | } 16 | 17 | type GaugeVec interface { 18 | WithLabelValues(lvs ...string) prometheus.Gauge 19 | GetMetricWithLabelValues(lvs ...string) (prometheus.Gauge, error) 20 | } 21 | 22 | type Histogram interface { 23 | Observe(float64) 24 | // Keep the Write method for testing purposes. 25 | Write(*dto.Metric) error 26 | } 27 | -------------------------------------------------------------------------------- /pkg/module/traces/types.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package traces 4 | 5 | import api "github.com/microsoft/retina/crd/api/v1alpha1" 6 | 7 | //go:generate go run go.uber.org/mock/mockgen@v0.4.0 -destination=mock_moduleinterface.go -copyright_file=../../lib/ignore_headers.txt -package=traces github.com/microsoft/retina/pkg/module/traces ModuleInterface 8 | 9 | type ModuleInterface interface { 10 | // Run starts the trace module. 11 | Run() 12 | 13 | Reconcile(spec *api.TracesSpec) error 14 | } 15 | -------------------------------------------------------------------------------- /pkg/plugin/common/constants.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package common 4 | 5 | const ( 6 | // MapPath is the path to pinned BPF maps 7 | MapPath = "/sys/fs/bpf" 8 | // FilterMapName is the name of the BPF filter map 9 | FilterMapName = "retina_filter" 10 | // ConntrackMapName is the name of the BPF conntrack map 11 | ConntrackMapName = "retina_conntrack" 12 | ) 13 | -------------------------------------------------------------------------------- /pkg/plugin/conntrack/_cprog/dynamic.h: -------------------------------------------------------------------------------- 1 | // Place holder header file that will be replaced by the actual header file during runtime 2 | // DO NOT DELETE 3 | -------------------------------------------------------------------------------- /pkg/plugin/conntrack/_cprog/placeholder.go: -------------------------------------------------------------------------------- 1 | package cprog //nolint:all 2 | 3 | // This file is a placeholder to make Go include this directory when vendoring. 4 | -------------------------------------------------------------------------------- /pkg/plugin/conntrack/conntrack_bpfel_arm64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/pkg/plugin/conntrack/conntrack_bpfel_arm64.o -------------------------------------------------------------------------------- /pkg/plugin/conntrack/conntrack_bpfel_x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/pkg/plugin/conntrack/conntrack_bpfel_x86.o -------------------------------------------------------------------------------- /pkg/plugin/conntrack/conntrack_windows.go: -------------------------------------------------------------------------------- 1 | package conntrack 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Conntrack struct{} 8 | 9 | // Not implemented for Windows 10 | func New() (*Conntrack, error) { 11 | return &Conntrack{}, nil 12 | } 13 | 14 | // Not implemented for Windows 15 | func (c *Conntrack) Run(_ context.Context) error { 16 | return nil 17 | } 18 | -------------------------------------------------------------------------------- /pkg/plugin/conntrack/doc.go: -------------------------------------------------------------------------------- 1 | // package conntrack provides the bpf code implementation for conntrack on Linux 2 | // and the userspace garbage collector program for the conntrack map. 3 | package conntrack 4 | -------------------------------------------------------------------------------- /pkg/plugin/dns/types_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package dns 4 | 5 | import ( 6 | v1 "github.com/cilium/cilium/pkg/hubble/api/v1" 7 | kcfg "github.com/microsoft/retina/pkg/config" 8 | "github.com/microsoft/retina/pkg/enricher" 9 | "github.com/microsoft/retina/pkg/log" 10 | "github.com/microsoft/retina/pkg/metrics" 11 | "github.com/microsoft/retina/pkg/plugin/common" 12 | ) 13 | 14 | const name = "dns" 15 | 16 | var m metrics.CounterVec 17 | 18 | type dns struct { 19 | cfg *kcfg.Config 20 | l *log.ZapLogger 21 | tracer common.ITracer 22 | pid uint32 23 | enricher enricher.EnricherInterface 24 | externalChannel chan *v1.Event 25 | } 26 | -------------------------------------------------------------------------------- /pkg/plugin/dropreason/_cprog/drop_reason.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | #include "vmlinux.h" 5 | 6 | typedef enum 7 | { 8 | IPTABLE_RULE_DROP = 0, 9 | IPTABLE_NAT_DROP, 10 | TCP_CONNECT_BASIC, 11 | TCP_ACCEPT_BASIC, 12 | TCP_CLOSE_BASIC, 13 | CONNTRACK_ADD_DROP, 14 | UNKNOWN_DROP, 15 | } drop_reason_t; 16 | 17 | #define NF_DROP 0 18 | 19 | // https://elixir.bootlin.com/linux/v5.4.156/source/include/uapi/asm-generic/errno-base.h#L26 20 | -------------------------------------------------------------------------------- /pkg/plugin/dropreason/_cprog/dynamic.h: -------------------------------------------------------------------------------- 1 | // Place holder header file that will be replaced by the actual header file during runtime 2 | // DO NOT DELETE 3 | -------------------------------------------------------------------------------- /pkg/plugin/dropreason/_cprog/placeholder.go: -------------------------------------------------------------------------------- 1 | package cprog //nolint:all 2 | 3 | // This file is a placeholder to make Go include this directory when vendoring. 4 | -------------------------------------------------------------------------------- /pkg/plugin/dropreason/kprobe_bpfel_arm64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/pkg/plugin/dropreason/kprobe_bpfel_arm64.o -------------------------------------------------------------------------------- /pkg/plugin/dropreason/kprobe_bpfel_x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/pkg/plugin/dropreason/kprobe_bpfel_x86.o -------------------------------------------------------------------------------- /pkg/plugin/filter/_cprog/placeholder.go: -------------------------------------------------------------------------------- 1 | package cprog //nolint:all 2 | 3 | // This file is a placeholder to make Go include this directory when vendoring. 4 | -------------------------------------------------------------------------------- /pkg/plugin/filter/_cprog/retina_filter.c: -------------------------------------------------------------------------------- 1 | //go:build ignore 2 | 3 | // Copyright (c) Microsoft Corporation. 4 | // Licensed under the MIT license. 5 | 6 | #include "vmlinux.h" 7 | #include "bpf_helpers.h" 8 | 9 | struct mapKey { 10 | __u32 prefixlen; 11 | __u32 data; 12 | }; 13 | 14 | struct { 15 | __uint(type, BPF_MAP_TYPE_LPM_TRIE); 16 | __type(key, struct mapKey); 17 | __type(value, __u8); 18 | __uint(map_flags, BPF_F_NO_PREALLOC); 19 | __uint(max_entries, 255); 20 | __uint(pinning, LIBBPF_PIN_BY_NAME); // Pinned to /sys/fs/bpf. 21 | } retina_filter SEC(".maps"); 22 | 23 | // Returns 1 if the IP address is in the map, 0 otherwise. 24 | bool lookup(__u32 ipaddr) 25 | { 26 | struct mapKey key = { 27 | .prefixlen = 32, 28 | .data = ipaddr 29 | }; 30 | 31 | if (bpf_map_lookup_elem(&retina_filter, &key)) 32 | return true; 33 | return false; 34 | } 35 | -------------------------------------------------------------------------------- /pkg/plugin/filter/filter_bpfel_arm64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/pkg/plugin/filter/filter_bpfel_arm64.o -------------------------------------------------------------------------------- /pkg/plugin/filter/filter_bpfel_x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/pkg/plugin/filter/filter_bpfel_x86.o -------------------------------------------------------------------------------- /pkg/plugin/filter/filter_map_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package filter 5 | 6 | import "net" 7 | 8 | type FilterMap struct{} 9 | 10 | func Init() (*FilterMap, error) { 11 | return &FilterMap{}, nil 12 | } 13 | 14 | func (f *FilterMap) Add(ips []net.IP) error { 15 | return nil 16 | } 17 | 18 | func (f *FilterMap) Delete(ips []net.IP) error { 19 | return nil 20 | } 21 | 22 | func (f *FilterMap) Close() { 23 | } 24 | -------------------------------------------------------------------------------- /pkg/plugin/filter/types.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package filter 5 | 6 | import ( 7 | "net" 8 | 9 | "github.com/cilium/ebpf" 10 | ) 11 | 12 | //go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=types.go -destination=mocks/mock_types.go -package=mocks 13 | 14 | /* 15 | A thin wrapper around the eBPF map that allows adding and deleting IPv4 addresses. 16 | Adding this separately here because: 17 | - C code uses the lib for generation/compilation 18 | - Plugins import retina_filter.c to use lookup function 19 | */ 20 | type IFilterMap interface { 21 | Add([]net.IP) error 22 | Delete([]net.IP) error 23 | Close() 24 | } 25 | 26 | // Interface for eBPF map. 27 | // Added for UTs. 28 | type IEbpfMap interface { 29 | BatchUpdate(keys, values interface{}, opts *ebpf.BatchOptions) (int, error) 30 | BatchDelete(keys interface{}, opts *ebpf.BatchOptions) (int, error) 31 | Put(key, value interface{}) error 32 | Delete(key interface{}) error 33 | Close() error 34 | } 35 | -------------------------------------------------------------------------------- /pkg/plugin/hnsstats/hnsstats_windows_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package hnsstats 4 | 5 | import ( 6 | "context" 7 | "testing" 8 | "time" 9 | 10 | kcfg "github.com/microsoft/retina/pkg/config" 11 | "github.com/microsoft/retina/pkg/log" 12 | "github.com/stretchr/testify/require" 13 | "golang.org/x/sync/errgroup" 14 | ) 15 | 16 | func TestShutdown(t *testing.T) { 17 | log.SetupZapLogger(log.GetDefaultLogOpts()) 18 | p := &hnsstats{ 19 | cfg: &kcfg.Config{ 20 | MetricsInterval: 100 * time.Second, 21 | EnablePodLevel: true, 22 | }, 23 | l: log.Logger().Named(name), 24 | } 25 | p.Init() 26 | ctx, cancel := context.WithCancel(context.Background()) 27 | g, errctx := errgroup.WithContext(ctx) 28 | 29 | g.Go(func() error { 30 | return p.Start(errctx) 31 | }) 32 | 33 | time.Sleep(1 * time.Second) 34 | cancel() 35 | err := g.Wait() 36 | require.NoError(t, err) 37 | } 38 | -------------------------------------------------------------------------------- /pkg/plugin/include_linux.go: -------------------------------------------------------------------------------- 1 | // nolint // don't complain about this file 2 | package plugin 3 | 4 | // Plugins self-register via their init() funcs as long as they are imported. 5 | import ( 6 | _ "github.com/microsoft/retina/pkg/plugin/ciliumeventobserver" 7 | _ "github.com/microsoft/retina/pkg/plugin/dns" 8 | _ "github.com/microsoft/retina/pkg/plugin/dropreason" 9 | _ "github.com/microsoft/retina/pkg/plugin/infiniband" 10 | _ "github.com/microsoft/retina/pkg/plugin/linuxutil" 11 | _ "github.com/microsoft/retina/pkg/plugin/mockplugin" 12 | _ "github.com/microsoft/retina/pkg/plugin/packetforward" 13 | _ "github.com/microsoft/retina/pkg/plugin/packetparser" 14 | _ "github.com/microsoft/retina/pkg/plugin/tcpretrans" 15 | ) 16 | -------------------------------------------------------------------------------- /pkg/plugin/include_windows.go: -------------------------------------------------------------------------------- 1 | // nolint // don't complain about this file 2 | package plugin 3 | 4 | // Plugins self-register via their init() funcs as long as they are imported. 5 | import ( 6 | _ "github.com/microsoft/retina/pkg/plugin/hnsstats" 7 | _ "github.com/microsoft/retina/pkg/plugin/pktmon" 8 | ) 9 | -------------------------------------------------------------------------------- /pkg/plugin/infiniband/Makefile: -------------------------------------------------------------------------------- 1 | REPO_ROOT = $(shell git rev-parse --show-toplevel) 2 | TOOLS_BIN_DIR = $(REPO_ROOT)/hack/tools/bin 3 | MOCKGEN = $(TOOLS_BIN_DIR)/mockgen 4 | 5 | .PHONY: generate 6 | 7 | generate: $(MOCKGEN) ## Generate mock clients 8 | $(MOCKGEN) -source=$(REPO_ROOT)/pkg/plugin/infiniband/types_linux.go -copyright_file=$(REPO_ROOT)/pkg/lib/ignore_headers.txt -package=infiniband > infiniband_mock_generated.go 9 | 10 | $(MOCKGEN): 11 | @make -C $(REPO_ROOT) $(MOCKGEN) 12 | -------------------------------------------------------------------------------- /pkg/plugin/infiniband/infiniband_mock_generated.go: -------------------------------------------------------------------------------- 1 | // Code generated by MockGen. DO NOT EDIT. 2 | // Source: types_linux.go 3 | // 4 | // Generated by this command: 5 | // 6 | // mockgen -source=types_linux.go -destination=infiniband_mock_generated.go -package=infiniband 7 | // 8 | 9 | // Package infiniband is a generated GoMock package. 10 | package infiniband 11 | -------------------------------------------------------------------------------- /pkg/plugin/infiniband/types_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package infiniband 4 | 5 | import ( 6 | "sync" 7 | 8 | kcfg "github.com/microsoft/retina/pkg/config" 9 | "github.com/microsoft/retina/pkg/log" 10 | ) 11 | 12 | const name = "infiniband" 13 | 14 | //go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=types_linux.go -destination=infiniband_mock_generated.go -package=infiniband 15 | type infiniband struct { 16 | cfg *kcfg.Config 17 | l *log.ZapLogger 18 | isRunning bool 19 | startLock sync.Mutex 20 | } 21 | 22 | type CounterStat struct { 23 | Name string 24 | Device string 25 | Port string 26 | } 27 | 28 | type StatusParam struct { 29 | Name string 30 | Iface string 31 | } 32 | -------------------------------------------------------------------------------- /pkg/plugin/lib/_amd64/placeholder.go: -------------------------------------------------------------------------------- 1 | package amd64 2 | 3 | // This file is a placeholder to make Go include this directory when vendoring. 4 | -------------------------------------------------------------------------------- /pkg/plugin/lib/_arm64/placeholder.go: -------------------------------------------------------------------------------- 1 | package arm64 2 | 3 | // This file is a placeholder to make Go include this directory when vendoring. 4 | -------------------------------------------------------------------------------- /pkg/plugin/lib/common/libbpf/_include/asm/barrier.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __ASM_BARRIER_H 3 | #define __ASM_BARRIER_H 4 | 5 | #include 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /pkg/plugin/lib/common/libbpf/_include/asm/placeholder.go: -------------------------------------------------------------------------------- 1 | package asm //nolint:all 2 | 3 | // This file is a placeholder to make Go include this directory when vendoring. 4 | -------------------------------------------------------------------------------- /pkg/plugin/lib/common/libbpf/_include/linux/err.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | 3 | #ifndef __LINUX_ERR_H 4 | #define __LINUX_ERR_H 5 | 6 | #include 7 | #include 8 | 9 | #define MAX_ERRNO 4095 10 | 11 | #define IS_ERR_VALUE(x) ((x) >= (unsigned long)-MAX_ERRNO) 12 | 13 | static inline void * ERR_PTR(long error_) 14 | { 15 | return (void *) error_; 16 | } 17 | 18 | static inline long PTR_ERR(const void *ptr) 19 | { 20 | return (long) ptr; 21 | } 22 | 23 | static inline bool IS_ERR(const void *ptr) 24 | { 25 | return IS_ERR_VALUE((unsigned long)ptr); 26 | } 27 | 28 | static inline bool IS_ERR_OR_NULL(const void *ptr) 29 | { 30 | return (!ptr) || IS_ERR_VALUE((unsigned long)ptr); 31 | } 32 | 33 | static inline long PTR_ERR_OR_ZERO(const void *ptr) 34 | { 35 | return IS_ERR(ptr) ? PTR_ERR(ptr) : 0; 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /pkg/plugin/lib/common/libbpf/_include/linux/placeholder.go: -------------------------------------------------------------------------------- 1 | package linux //nolint:all 2 | 3 | // This file is a placeholder to make Go include this directory when vendoring. 4 | -------------------------------------------------------------------------------- /pkg/plugin/lib/common/libbpf/_include/linux/ring_buffer.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef _TOOLS_LINUX_RING_BUFFER_H_ 3 | #define _TOOLS_LINUX_RING_BUFFER_H_ 4 | 5 | #include 6 | 7 | static inline __u64 ring_buffer_read_head(struct perf_event_mmap_page *base) 8 | { 9 | return smp_load_acquire(&base->data_head); 10 | } 11 | 12 | static inline void ring_buffer_write_tail(struct perf_event_mmap_page *base, 13 | __u64 tail) 14 | { 15 | smp_store_release(&base->data_tail, tail); 16 | } 17 | 18 | #endif /* _TOOLS_LINUX_RING_BUFFER_H_ */ 19 | -------------------------------------------------------------------------------- /pkg/plugin/lib/common/libbpf/_include/linux/types.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | 3 | #ifndef __LINUX_TYPES_H 4 | #define __LINUX_TYPES_H 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #define __bitwise__ 16 | #define __bitwise __bitwise__ 17 | 18 | typedef __u16 __bitwise __le16; 19 | typedef __u16 __bitwise __be16; 20 | typedef __u32 __bitwise __le32; 21 | typedef __u32 __bitwise __be32; 22 | typedef __u64 __bitwise __le64; 23 | typedef __u64 __bitwise __be64; 24 | 25 | #ifndef __aligned_u64 26 | # define __aligned_u64 __u64 __attribute__((aligned(8))) 27 | #endif 28 | 29 | struct list_head { 30 | struct list_head *next, *prev; 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /pkg/plugin/lib/common/libbpf/_include/uapi/linux/placeholder.go: -------------------------------------------------------------------------------- 1 | package uapi //nolint:all 2 | 3 | // This file is a placeholder to make Go include this directory when vendoring. 4 | -------------------------------------------------------------------------------- /pkg/plugin/lib/common/libbpf/_src/libbpf_version.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | /* Copyright (C) 2021 Facebook */ 3 | #ifndef __LIBBPF_VERSION_H 4 | #define __LIBBPF_VERSION_H 5 | 6 | #define LIBBPF_MAJOR_VERSION 1 7 | #define LIBBPF_MINOR_VERSION 5 8 | 9 | #endif /* __LIBBPF_VERSION_H */ 10 | -------------------------------------------------------------------------------- /pkg/plugin/lib/common/libbpf/_src/placeholder.go: -------------------------------------------------------------------------------- 1 | package libbpf //nolint:all 2 | 3 | // This file is a placeholder to make Go include this directory when vendoring. 4 | -------------------------------------------------------------------------------- /pkg/plugin/lib/common/libbpf/_src/str_error.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __LIBBPF_STR_ERROR_H 3 | #define __LIBBPF_STR_ERROR_H 4 | 5 | #define STRERR_BUFSIZE 128 6 | 7 | char *libbpf_strerror_r(int err, char *dst, int len); 8 | 9 | #endif /* __LIBBPF_STR_ERROR_H */ 10 | -------------------------------------------------------------------------------- /pkg/plugin/lib/common/libbpf/_src/strset.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | 3 | /* Copyright (c) 2021 Facebook */ 4 | #ifndef __LIBBPF_STRSET_H 5 | #define __LIBBPF_STRSET_H 6 | 7 | #include 8 | #include 9 | 10 | struct strset; 11 | 12 | struct strset *strset__new(size_t max_data_sz, const char *init_data, size_t init_data_sz); 13 | void strset__free(struct strset *set); 14 | 15 | const char *strset__data(const struct strset *set); 16 | size_t strset__data_size(const struct strset *set); 17 | 18 | int strset__find_str(struct strset *set, const char *s); 19 | int strset__add_str(struct strset *set, const char *s); 20 | 21 | #endif /* __LIBBPF_STRSET_H */ 22 | -------------------------------------------------------------------------------- /pkg/plugin/linuxutil/Makefile: -------------------------------------------------------------------------------- 1 | REPO_ROOT = $(shell git rev-parse --show-toplevel) 2 | TOOLS_BIN_DIR = $(REPO_ROOT)/hack/tools/bin 3 | MOCKGEN = $(TOOLS_BIN_DIR)/mockgen 4 | 5 | .PHONY: generate 6 | 7 | generate: $(MOCKGEN) ## Generate mock clients 8 | $(MOCKGEN) -source=$(REPO_ROOT)/pkg/plugin/linuxutil/types_linux.go -copyright_file=$(REPO_ROOT)/pkg/lib/ignore_headers.txt -package=linuxutil > linuxutil_mock_generated_linux.go 9 | 10 | $(MOCKGEN): 11 | @make -C $(REPO_ROOT) $(MOCKGEN) 12 | -------------------------------------------------------------------------------- /pkg/plugin/linuxutil/testdata/somecorrect-netstat1: -------------------------------------------------------------------------------- 1 | TcpExt: SyncookiesSent 2 | TcpExt: 12 0 0 0 0 0 0 0 3 | IpExt: InNoRoutes InTruncatedPkts 4 | IpExt: 18965 0 5 | MPTcpExt: Test1 6 | MPTcpExt: 10 7 | Test 8 | Test 9 | Test2: 1 10 | Test2 11 | -------------------------------------------------------------------------------- /pkg/plugin/linuxutil/testdata/wrong-netstat: -------------------------------------------------------------------------------- 1 | Test: aa aa aa 2 | -------------------------------------------------------------------------------- /pkg/plugin/packetforward/_cprog/packetforward.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | #include "vmlinux.h" 5 | 6 | typedef enum 7 | { 8 | INGRESS_KEY = 0, 9 | EGRESS_KEY, 10 | } key_type; 11 | -------------------------------------------------------------------------------- /pkg/plugin/packetforward/_cprog/placeholder.go: -------------------------------------------------------------------------------- 1 | package cprog //nolint:all 2 | 3 | // This file is a placeholder to make Go include this directory when vendoring. 4 | -------------------------------------------------------------------------------- /pkg/plugin/packetforward/packetforward_bpfel_arm64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/pkg/plugin/packetforward/packetforward_bpfel_arm64.o -------------------------------------------------------------------------------- /pkg/plugin/packetforward/packetforward_bpfel_x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/pkg/plugin/packetforward/packetforward_bpfel_x86.o -------------------------------------------------------------------------------- /pkg/plugin/packetparser/_cprog/dynamic.h: -------------------------------------------------------------------------------- 1 | #define BYPASS_LOOKUP_IP_OF_INTEREST 0 2 | #define DATA_AGGREGATION_LEVEL 0 3 | -------------------------------------------------------------------------------- /pkg/plugin/packetparser/_cprog/packetparser.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | #define ETH_P_IP 0x0800 5 | // The maximum length of the TCP options field. 6 | #define MAX_TCP_OPTIONS_LEN 40 7 | // tc-bpf return code to execute the next tc-bpf program. 8 | #define TC_ACT_UNSPEC (-1) 9 | 10 | #define DATA_AGGREGATION_LEVEL_LOW 0 11 | #define DATA_AGGREGATION_LEVEL_HIGH 1 12 | -------------------------------------------------------------------------------- /pkg/plugin/packetparser/_cprog/placeholder.go: -------------------------------------------------------------------------------- 1 | package cprog //nolint:all 2 | 3 | // This file is a placeholder to make Go include this directory when vendoring. 4 | -------------------------------------------------------------------------------- /pkg/plugin/packetparser/packetparser_bpfel_arm64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/pkg/plugin/packetparser/packetparser_bpfel_arm64.o -------------------------------------------------------------------------------- /pkg/plugin/packetparser/packetparser_bpfel_x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/pkg/plugin/packetparser/packetparser_bpfel_x86.o -------------------------------------------------------------------------------- /pkg/plugin/plugin.go: -------------------------------------------------------------------------------- 1 | // package plugin aliases types from plugin/registry to prevent import cycles. 2 | package plugin 3 | 4 | import "github.com/microsoft/retina/pkg/plugin/registry" 5 | 6 | //go:generate go run go.uber.org/mock/mockgen@v0.4.0 -destination=mock/plugin.go -copyright_file=../lib/ignore_headers.txt -package=plugin github.com/microsoft/retina/pkg/plugin Plugin 7 | 8 | type ( 9 | Plugin = registry.Plugin 10 | Func = registry.PluginFunc 11 | ) 12 | 13 | func Get(name string) (Func, bool) { 14 | return registry.Get(name) 15 | } 16 | -------------------------------------------------------------------------------- /pkg/plugin/tcpretrans/types_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package tcpretrans 4 | 5 | import ( 6 | "errors" 7 | 8 | gadgetcontext "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-context" 9 | "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/tcpretrans/tracer" 10 | kcfg "github.com/microsoft/retina/pkg/config" 11 | "github.com/microsoft/retina/pkg/enricher" 12 | "github.com/microsoft/retina/pkg/log" 13 | ) 14 | 15 | const name = "tcpretrans" 16 | 17 | type tcpretrans struct { 18 | cfg *kcfg.Config 19 | l *log.ZapLogger 20 | tracer *tracer.Tracer 21 | gadgetCtx *gadgetcontext.GadgetContext 22 | enricher enricher.EnricherInterface 23 | } 24 | 25 | var errEnricherNotInitialized = errors.New("enricher not initialized") 26 | -------------------------------------------------------------------------------- /pkg/provider/azure/clients/doc.go: -------------------------------------------------------------------------------- 1 | // package clients provides the Azure clients for the operator to interact with Azure services. 2 | package clients 3 | -------------------------------------------------------------------------------- /pkg/provider/azure/clients/types.go: -------------------------------------------------------------------------------- 1 | package clients 2 | 3 | import ( 4 | "sigs.k8s.io/cloud-provider-azure/pkg/azclient" 5 | ) 6 | 7 | // AzureConfig represents the configuration for Azure clients. 8 | type AzureConfig struct { 9 | azclient.AzureAuthConfig `json:",inline" yaml:",inline"` 10 | azclient.ARMClientConfig `json:",inline" yaml:",inline"` 11 | 12 | SubscriptionID string `json:"subscriptionID,omitempty"` 13 | // The name of the resource group that the cluster is deployed in 14 | ResourceGroup string `json:"resourceGroup,omitempty" yaml:"resourceGroup,omitempty"` 15 | // The location of the resource group that the cluster is deployed in 16 | Location string `json:"location,omitempty" yaml:"location,omitempty"` 17 | } 18 | -------------------------------------------------------------------------------- /pkg/pubsub/types.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package pubsub 4 | 5 | type CallBackFunc func(interface{}) 6 | 7 | //go:generate go run go.uber.org/mock/mockgen@v0.4.0 -destination=mock_pubsubinterface.go -copyright_file=../lib/ignore_headers.txt -package=pubsub github.com/microsoft/retina/pkg/pubsub PubSubInterface 8 | 9 | // this file defines the interface a simple pubsub implementation should implement 10 | type PubSubInterface interface { 11 | // Publish publishes the given message to the given topic 12 | Publish(topic PubSubTopic, msg interface{}) 13 | // Subscribe subscribes to the given topic and calls the given callback function 14 | // when a message is published to the topic 15 | Subscribe(topic PubSubTopic, callback *CallBackFunc) string 16 | // Unsubscribe unsubscribes from the given topic 17 | Unsubscribe(topic PubSubTopic, uuid string) error 18 | } 19 | 20 | type PubSubTopic string 21 | -------------------------------------------------------------------------------- /pkg/shared/config/config_linux.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cilium/hive/cell" 7 | "k8s.io/client-go/rest" 8 | kcfg "sigs.k8s.io/controller-runtime/pkg/client/config" 9 | ) 10 | 11 | var Cell = cell.Module( 12 | "shared-config", 13 | "Shared Config", 14 | cell.Provide(GetK8sConfig), 15 | ) 16 | 17 | func GetK8sConfig() (*rest.Config, error) { 18 | k8sCfg, err := kcfg.GetConfig() 19 | if err != nil { 20 | return &rest.Config{}, fmt.Errorf("failed to get k8s config: %w", err) 21 | } 22 | return k8sCfg, nil 23 | } 24 | -------------------------------------------------------------------------------- /pkg/shared/config/type.go: -------------------------------------------------------------------------------- 1 | // Placeholder file. Required for windows build and lint. 2 | package config 3 | -------------------------------------------------------------------------------- /pkg/shared/telemetry/type.go: -------------------------------------------------------------------------------- 1 | // Placeholder file. Required for windows build and lint. 2 | package telemetry 3 | -------------------------------------------------------------------------------- /pkg/telemetry/consts.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package telemetry 5 | 6 | const ( 7 | // PropertyApiVersion is the property name of the telemetry item that contains the APIServer endpoint. 8 | // apiserver is used to distinguish the telemetry items from different Kubernetes clusters and should be uniformed 9 | // across all the telemetry items from the same cluster with the format http(s)://:. 10 | // For example "https://retina-test-c4528d-zn0ugsna.hcp.southeastasia.azmk8s.io:443 11 | PropertyApiserver = "apiserver" 12 | ) 13 | 14 | const ( 15 | EnvPodName = "POD_NAME" 16 | ) 17 | -------------------------------------------------------------------------------- /pkg/telemetry/heartbeat_unix.go: -------------------------------------------------------------------------------- 1 | //go:build unix 2 | 3 | // Copyright (c) Microsoft Corporation. 4 | // Licensed under the MIT license. 5 | 6 | package telemetry 7 | 8 | import ( 9 | "context" 10 | "os/exec" 11 | "strings" 12 | 13 | "github.com/pkg/errors" 14 | ) 15 | 16 | func KernelVersion(ctx context.Context) (string, error) { 17 | cmd := exec.CommandContext(ctx, "uname", "-r") 18 | output, err := cmd.CombinedOutput() 19 | if err != nil { 20 | return "", errors.Wrapf(err, "failed to get linux kernel version: %s", string(output)) 21 | } 22 | return strings.TrimSuffix(string(output), "\n"), nil 23 | } 24 | -------------------------------------------------------------------------------- /pkg/telemetry/heartbeat_unix_test.go: -------------------------------------------------------------------------------- 1 | //go:build unix 2 | 3 | // Copyright (c) Microsoft Corporation. 4 | // Licensed under the MIT license. 5 | 6 | package telemetry 7 | 8 | import ( 9 | "context" 10 | "testing" 11 | 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestLinuxPlatformKernelVersion(t *testing.T) { 16 | InitAppInsights("", "") 17 | ctx := context.TODO() 18 | 19 | str, err := KernelVersion(ctx) 20 | require.NoError(t, err) 21 | require.NotEmpty(t, str) 22 | } 23 | -------------------------------------------------------------------------------- /pkg/telemetry/heartbeat_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package telemetry 5 | 6 | import ( 7 | "context" 8 | "os/exec" 9 | "strings" 10 | 11 | "github.com/pkg/errors" 12 | ) 13 | 14 | func KernelVersion(ctx context.Context) (string, error) { 15 | cmd := exec.CommandContext(ctx, "powershell", "-command", "$([Environment]::OSVersion).VersionString") 16 | output, err := cmd.CombinedOutput() 17 | if err != nil { 18 | return "", errors.Wrapf(err, "failed to get windows kernel version: %s", string(output)) 19 | } 20 | return strings.TrimSuffix(string(output), "\r\n"), nil 21 | } 22 | -------------------------------------------------------------------------------- /pkg/telemetry/heartbeat_windows_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package telemetry 5 | 6 | import ( 7 | "context" 8 | "testing" 9 | 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func TestWindowsGetKernelVersion(t *testing.T) { 14 | InitAppInsights("", "") 15 | ctx := context.TODO() 16 | 17 | str, err := KernelVersion(ctx) 18 | require.NoError(t, err) 19 | require.NotEmpty(t, str) 20 | } 21 | -------------------------------------------------------------------------------- /pkg/telemetry/noop_perf.go: -------------------------------------------------------------------------------- 1 | package telemetry 2 | 3 | type NoopPerfProfile struct{} 4 | 5 | func (n *NoopPerfProfile) GetMemoryUsage() map[string]string { 6 | return make(map[string]string) 7 | } 8 | 9 | func NewNoopPerfProfile() *NoopPerfProfile { 10 | return &NoopPerfProfile{} 11 | } 12 | 13 | func (n *NoopPerfProfile) GetCPUUsage() (map[string]string, error) { //nolint unnamed results are fine 14 | return make(map[string]string), nil 15 | } 16 | -------------------------------------------------------------------------------- /pkg/telemetry/noop_telemetry.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package telemetry 5 | 6 | import ( 7 | "context" 8 | "time" 9 | 10 | "github.com/microsoft/ApplicationInsights-Go/appinsights/contracts" 11 | ) 12 | 13 | func NewNoopTelemetry() *NoopTelemetry { 14 | return &NoopTelemetry{} 15 | } 16 | 17 | type NoopTelemetry struct{} 18 | 19 | func (m NoopTelemetry) StartPerf(functionName string) *PerformanceCounter { 20 | return &PerformanceCounter{} 21 | } 22 | 23 | func (m NoopTelemetry) StopPerf(counter *PerformanceCounter) { 24 | } 25 | 26 | func (m NoopTelemetry) Heartbeat(ctx context.Context, heartbeatInterval time.Duration) { 27 | } 28 | 29 | func (m NoopTelemetry) TrackEvent(name string, properties map[string]string) { 30 | } 31 | 32 | func (m NoopTelemetry) TrackMetric(name string, value float64, properties map[string]string) { 33 | } 34 | 35 | func (m NoopTelemetry) TrackTrace(name string, severity contracts.SeverityLevel, properties map[string]string) { 36 | } 37 | -------------------------------------------------------------------------------- /pkg/telemetry/perf.go: -------------------------------------------------------------------------------- 1 | package telemetry 2 | 3 | type Perf interface { 4 | GetMemoryUsage() map[string]string 5 | GetCPUUsage() (map[string]string, error) 6 | } 7 | -------------------------------------------------------------------------------- /pkg/telemetry/perf_windows.go: -------------------------------------------------------------------------------- 1 | package telemetry 2 | 3 | import ( 4 | "runtime" 5 | "strconv" 6 | ) 7 | 8 | type PerfProfile struct{} 9 | 10 | func (p *PerfProfile) GetMemoryUsage() map[string]string { 11 | var m runtime.MemStats 12 | runtime.ReadMemStats(&m) 13 | props := map[string]string{ 14 | heapalloc: strconv.FormatUint(bToMb(m.HeapAlloc), 10), 15 | sysmem: strconv.FormatUint(bToMb(m.Sys), 10), 16 | goroutines: strconv.Itoa(runtime.NumGoroutine()), 17 | } 18 | return props 19 | } 20 | 21 | func NewPerfProfile() (*PerfProfile, error) { 22 | return &PerfProfile{}, nil 23 | } 24 | 25 | func (p *PerfProfile) GetCPUUsage() (map[string]string, error) { //nolint unnamed results are fine 26 | return make(map[string]string), nil 27 | } 28 | -------------------------------------------------------------------------------- /pkg/telemetry/utils.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package telemetry 5 | 6 | import ( 7 | kcfg "sigs.k8s.io/controller-runtime/pkg/client/config" 8 | ) 9 | 10 | // GetK8SApiserverURLFromKubeConfig returns apiserver URL from kubeconfig. 11 | // The apiserver URL is expected to be publicly unique identifier of the Kubernetes cluster. 12 | // In case the kubeconfig does not exists, this identifier can be obtained for pods from kube-system namespace. 13 | // Kubelet will populate env KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT for Pods deployed in kube-system 14 | // namespace, which can be used to generate apiserver URL from `GetConfig()`. 15 | func GetK8SApiserverURLFromKubeConfig() (string, error) { 16 | cfg, err := kcfg.GetConfig() 17 | if err != nil { 18 | return "", err 19 | } 20 | return cfg.Host, nil 21 | } 22 | -------------------------------------------------------------------------------- /pkg/utils/metadata_linux.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package utils; 3 | 4 | option go_package = "github.com/microsoft/retina/pkg/utils"; 5 | 6 | message RetinaMetadata { 7 | uint32 bytes = 1; 8 | 9 | // DNS metadata. 10 | DNSType dns_type = 2; 11 | uint32 num_responses = 3; 12 | 13 | // TCP ID. Either Tsval or Tsecr will be set. 14 | uint64 tcp_id = 4; 15 | 16 | // Drop reason in Retina. 17 | DropReason drop_reason = 5; 18 | } 19 | 20 | enum DNSType { 21 | UNKNOWN = 0; 22 | QUERY = 1; 23 | RESPONSE = 2; 24 | } 25 | 26 | // Ref: pkg/plugin/dropreason/_cprog/drop_reason.h. 27 | enum DropReason { 28 | IPTABLE_RULE_DROP = 0; 29 | IPTABLE_NAT_DROP = 1; 30 | TCP_CONNECT_BASIC = 2; 31 | TCP_ACCEPT_BASIC = 3; 32 | TCP_CLOSE_BASIC = 4; 33 | CONNTRACK_ADD_DROP = 5; 34 | UNKNOWN_DROP = 6; 35 | } 36 | -------------------------------------------------------------------------------- /pkg/utils/testutil/cilium/errors.go: -------------------------------------------------------------------------------- 1 | //go:unit 2 | 3 | package ciliumutil 4 | 5 | import ( 6 | "github.com/pkg/errors" 7 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | ) 9 | 10 | var ( 11 | ErrAlreadyExists = errors.New("already exists") 12 | ErrNotImplemented = errors.New("not implemented") 13 | ) 14 | 15 | const ErrCodeNotFound = 404 16 | 17 | type ErrNotFound struct{} 18 | 19 | func (e ErrNotFound) Error() string { 20 | return "not found on API server" 21 | } 22 | 23 | func (e ErrNotFound) Status() v1.Status { 24 | return v1.Status{ 25 | Reason: v1.StatusReasonNotFound, 26 | Code: ErrCodeNotFound, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /pkg/utils/testutil/cilium/errors_test.go: -------------------------------------------------------------------------------- 1 | package ciliumutil 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | apierrors "k8s.io/apimachinery/pkg/api/errors" 9 | ) 10 | 11 | func TestErrNotFound(t *testing.T) { 12 | err := ErrNotFound{} 13 | require.True(t, apierrors.IsNotFound(err)) 14 | } 15 | -------------------------------------------------------------------------------- /pkg/utils/utils_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | package utils 4 | 5 | import ( 6 | "github.com/cilium/cilium/api/v1/flow" 7 | ) 8 | 9 | func GetDropReasonDesc(dr DropReason) flow.DropReason { 10 | switch dr { //nolint:exhaustive // We are handling all the cases. 11 | case DropReason_Drop_INET_FinWait2: 12 | return flow.DropReason_UNKNOWN_CONNECTION_TRACKING_STATE 13 | default: 14 | return flow.DropReason_DROP_REASON_UNKNOWN 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pkg/watchers/apiserver/types.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | package apiserver 5 | 6 | import "context" 7 | 8 | //go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=types.go -destination=mocks/mock_types.go -package=mocks . 9 | type IHostResolver interface { 10 | LookupHost(context context.Context, host string) ([]string, error) 11 | } 12 | 13 | // define cache as a set 14 | type cache map[string]struct{} 15 | 16 | func (c cache) deepcopy() cache { 17 | copy := make(cache) 18 | for k, v := range c { 19 | copy[k] = v 20 | } 21 | return copy 22 | } 23 | -------------------------------------------------------------------------------- /pkg/watchers/endpoint/endpoint_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | /* Template */ 5 | 6 | package endpoint 7 | 8 | import ( 9 | "github.com/Microsoft/hcsshim/hcn" 10 | ) 11 | 12 | func (e *EndpointWatcher) initNewCache() error { 13 | return nil 14 | } 15 | 16 | func listVeths() ([]hcn.HostComputeEndpoint, error) { 17 | return nil, nil 18 | } 19 | -------------------------------------------------------------------------------- /samples/capture/capture-specific-pod-on-a-node.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: retina.sh/v1alpha1 2 | kind: Capture 3 | metadata: 4 | name: capture-pod-blobupload 5 | spec: 6 | captureConfiguration: 7 | captureOption: 8 | duration: 10m 9 | captureTarget: 10 | nodeSelector: 11 | matchExpressions: 12 | - { 13 | key: kubernetes.io/hostname, 14 | operator: In, 15 | values: [aks-nodepool1-11396069-vmss000001], 16 | } 17 | filters: 18 | # Include packets from/to the following IP addresses or IP:Port pairs 19 | include: 20 | - 10.224.0.128:80 21 | - 10.224.0.129 22 | # Comment the following code out to exclude packets from/to IMDS server 23 | # exclude: 24 | # - 169.254.169.254 25 | outputConfiguration: 26 | # the artifact will be copied to hostpath 27 | # and uploaded to azure storage account 28 | hostPath: "/tmp/retina" 29 | blobUpload: blobsassecret 30 | -------------------------------------------------------------------------------- /samples/capture/nodeblobupload.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: retina.sh/v1alpha1 2 | kind: Capture 3 | metadata: 4 | name: capture-node-blobupload 5 | spec: 6 | captureConfiguration: 7 | captureOption: 8 | duration: 10m 9 | captureTarget: 10 | nodeSelector: 11 | matchExpressions: 12 | - { 13 | key: kubernetes.io/hostname, 14 | operator: In, 15 | values: 16 | [ 17 | aks-nodepool1-11396069-vmss000001, 18 | aks-nodepool1-11396069-vmss000000, 19 | ], 20 | } 21 | outputConfiguration: 22 | hostPath: "/tmp/retina" 23 | blobUpload: blobsassecret 24 | -------------------------------------------------------------------------------- /samples/capture/podblobupload.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: retina.sh/v1alpha1 2 | kind: Capture 3 | metadata: 4 | name: capture-pod-blobupload 5 | spec: 6 | captureConfiguration: 7 | captureOption: 8 | duration: 10m 9 | captureTarget: 10 | podSelector: 11 | matchLabels: 12 | k8s-app: cloud-node-manager 13 | namespaceSelector: 14 | matchLabels: 15 | kubernetes.io/metadata.name: kube-system 16 | outputConfiguration: 17 | # the artifact will be copied to hostpath 18 | # and uploaded to azure storage account 19 | hostPath: "/tmp/retina" 20 | blobUpload: blobsassecret 21 | -------------------------------------------------------------------------------- /samples/metricsconfiguration.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: retina.sh/v1alpha1 2 | kind: MetricsConfiguration 3 | metadata: 4 | name: sample-metricsconfig 5 | spec: 6 | contextOptions: 7 | - metricName: requests_total 8 | sourceLabels: 9 | - source 10 | additionalLabels: 11 | - direction 12 | namespaces: 13 | include: 14 | - default 15 | exclude: 16 | - kube-system 17 | -------------------------------------------------------------------------------- /scripts/coverage/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | We use GITHUB_TOKEN to get the following: 4 | 5 | 1. Workflow ID with the retina test yaml 6 | 2. Get the latest main branch successful workflow run with that id 7 | 3. Get the artifacts from that run and download them 8 | 9 | ## Testing Locally 10 | 11 | 1. Set your PAT from github developer settings as `GITHUB_TOKEN` env variable 12 | https: //docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token#creating-a-personal-access-token-classic 13 | 2. Set a test PR number as `PULL_REQUEST_NUMBER` env variable 14 | 3. generate coverage.out for local branch with `go test -coverprofile=coverage.out ./...` 15 | 4. run `make coverage` on your local branch and not main. 16 | -------------------------------------------------------------------------------- /scripts/windows.ps1: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. 2 | # Licensed under the MIT license. 3 | # example usage: 4 | # powershell.exe -command "& { . .\windows.ps1; controller-image }" 5 | # Retry({retina-image $(tag)-windows-amd64}) 6 | 7 | function Retry([Action]$action) { 8 | $attempts = 3 9 | $sleepInSeconds = 5 10 | do { 11 | try { 12 | $action.Invoke(); 13 | break; 14 | } 15 | catch [Exception] { 16 | Write-Host $_.Exception.Message 17 | } 18 | $attempts-- 19 | if ($attempts -gt 0) { 20 | sleep $sleepInSeconds 21 | } 22 | } while ($attempts -gt 0) 23 | } 24 | 25 | function retina-image { 26 | if ($null -eq $env:TAG) { $env:TAG = $args[0] } 27 | docker build ` 28 | -f .\Dockerfile.windows ` 29 | -t ghcr.io/microsoft/retina/retina-agent:$env:TAG ` 30 | . 31 | } 32 | -------------------------------------------------------------------------------- /shell/Dockerfile: -------------------------------------------------------------------------------- 1 | # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" 2 | FROM mcr.microsoft.com/azurelinux/base/core@sha256:b46476be0b5c9691ad20f78871819950c01433bdfad81d72c61618f4a6202b25 3 | 4 | RUN tdnf install -y \ 5 | bind-utils \ 6 | conntrack \ 7 | curl \ 8 | ebtables-legacy \ 9 | ethtool \ 10 | iperf3 \ 11 | iproute \ 12 | ipset \ 13 | iptables \ 14 | iputils \ 15 | jq \ 16 | ldns-utils \ 17 | less \ 18 | net-tools \ 19 | nftables \ 20 | nmap \ 21 | nmap-ncat \ 22 | openssh \ 23 | socat \ 24 | tcpdump \ 25 | wget \ 26 | && tdnf clean all 27 | 28 | CMD ["/bin/bash", "-l"] 29 | -------------------------------------------------------------------------------- /shell/README.md: -------------------------------------------------------------------------------- 1 | # retina-shell 2 | 3 | Retina CLI provides a command to launch an interactive shell in a node or pod for adhoc debugging. 4 | 5 | * The CLI command `kubectl retina shell` creates a pod with `HostNetwork=true` (for node debugging) or an ephemeral container in an existing pod (for pod debugging). 6 | * The container runs an image built from the Dockerfile in this directory. The image is based on Azure Linux and includes commonly-used networking tools. 7 | 8 | For testing, you can override the image used by `retina shell` either with CLI arguments 9 | (`--retina-shell-image-repo` and `--retina-shell-image-version`) or environment variables 10 | (`RETINA_SHELL_IMAGE_REPO` and `RETINA_SHELL_IMAGE_VERSION`). 11 | 12 | Run `kubectl retina shell -h` for full documentation and examples. 13 | 14 | Currently only Linux is supported; Windows support will be added in the future. 15 | -------------------------------------------------------------------------------- /shell/validation.go: -------------------------------------------------------------------------------- 1 | package shell 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "fmt" 7 | 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | "k8s.io/client-go/kubernetes" 10 | ) 11 | 12 | var errUnsupportedOperatingSystem = errors.New("unsupported OS (retina-shell requires Linux)") 13 | 14 | func validateOperatingSystemSupportedForNode(ctx context.Context, clientset *kubernetes.Clientset, nodeName string) error { 15 | node, err := clientset.CoreV1(). 16 | Nodes(). 17 | Get(ctx, nodeName, metav1.GetOptions{}) 18 | if err != nil { 19 | return fmt.Errorf("error retrieving node %s: %w", nodeName, err) 20 | } 21 | 22 | osLabel := node.Labels["kubernetes.io/os"] 23 | if osLabel != "linux" { // Only Linux supported for now. 24 | return errUnsupportedOperatingSystem 25 | } 26 | 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /site/.gitignore: -------------------------------------------------------------------------------- 1 | public/ 2 | external-docs/ 3 | tools/__pycache__/ 4 | docs/ 5 | docs 6 | versioned_docs/ 7 | versioned_sidebars/ 8 | versions.json 9 | node_modules/ 10 | 11 | # Dependencies 12 | /node_modules 13 | 14 | # Production 15 | /build 16 | 17 | # Generated files 18 | .docusaurus 19 | .cache-loader 20 | 21 | # Misc 22 | .DS_Store 23 | .env.local 24 | .env.development.local 25 | .env.test.local 26 | .env.production.local 27 | 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | -------------------------------------------------------------------------------- /site/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. 4 | 5 | ## Development 6 | 7 | When adding a new doc, make sure to add it to `/site/sidebars.js` to display it in the sidebar. 8 | 9 | > Prerequisite: [Docker](https://docs.docker.com/engine/install/) 10 | 11 | To test your changes, run `make docs` from the root directory to spin up local webserver and view changes with hot reload. 12 | -------------------------------------------------------------------------------- /site/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /site/sidebars.ts: -------------------------------------------------------------------------------- 1 | import type { SidebarsConfig } from "@docusaurus/plugin-content-docs"; 2 | const sidebars : SidebarsConfig = { 3 | mainSidebar: [{type: 'autogenerated', dirName: '.'}], 4 | }; 5 | 6 | export default sidebars; 7 | -------------------------------------------------------------------------------- /site/site/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "site", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": {} 6 | } 7 | -------------------------------------------------------------------------------- /site/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import LandingPage from "../components/LandingPage"; 2 | 3 | export default LandingPage; -------------------------------------------------------------------------------- /site/start-dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | npm install --prefix site 3 | npm start --prefix site -- --host 0.0.0.0 4 | -------------------------------------------------------------------------------- /site/static/img/Retina-logo-horizontal-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/site/static/img/Retina-logo-horizontal-white.png -------------------------------------------------------------------------------- /site/static/img/Retina-logo-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/site/static/img/Retina-logo-horizontal.png -------------------------------------------------------------------------------- /site/static/img/Retina-logo-vertical-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/site/static/img/Retina-logo-vertical-white.png -------------------------------------------------------------------------------- /site/static/img/Retina-logo-vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/site/static/img/Retina-logo-vertical.png -------------------------------------------------------------------------------- /site/static/img/Retina-logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/site/static/img/Retina-logo-white.png -------------------------------------------------------------------------------- /site/static/img/Retina-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/site/static/img/Retina-logo.png -------------------------------------------------------------------------------- /site/static/img/retina-social-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/site/static/img/retina-social-card.png -------------------------------------------------------------------------------- /site/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@docusaurus/tsconfig", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/e2e/framework/azure/get-fqdn.go: -------------------------------------------------------------------------------- 1 | package azure 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/Azure/azure-sdk-for-go/sdk/azidentity" 8 | armcontainerservice "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4" 9 | ) 10 | 11 | func GetFqdnFn(subscriptionId, resourceGroupName, clusterName string) (string, error) { 12 | cred, err := azidentity.NewAzureCLICredential(nil) 13 | if err != nil { 14 | return "", fmt.Errorf("failed to obtain a credential: %w", err) 15 | } 16 | ctx := context.Background() 17 | clientFactory, err := armcontainerservice.NewClientFactory(subscriptionId, cred, nil) 18 | if err != nil { 19 | return "", fmt.Errorf("failed to create client: %w", err) 20 | } 21 | res, err := clientFactory.NewManagedClustersClient().Get(ctx, resourceGroupName, clusterName, nil) 22 | if err != nil { 23 | return "", fmt.Errorf("failed to finish the get managed cluster client request: %w", err) 24 | } 25 | 26 | return *res.Properties.Fqdn, nil 27 | } 28 | -------------------------------------------------------------------------------- /test/e2e/framework/params/params.go: -------------------------------------------------------------------------------- 1 | package params 2 | 3 | import ( 4 | "os" 5 | ) 6 | 7 | var ( 8 | Location = os.Getenv("LOCATION") 9 | SubscriptionID = os.Getenv("AZURE_SUBSCRIPTION_ID") 10 | ResourceGroup = os.Getenv("AZURE_RESOURCE_GROUP") 11 | ClusterName = os.Getenv("CLUSTER_NAME") 12 | Nodes = os.Getenv("NODES") 13 | NumDeployments = os.Getenv("NUM_DEPLOYMENTS") 14 | NumReplicas = os.Getenv("NUM_REPLICAS") 15 | NumNetworkPolicies = os.Getenv("NUM_NET_POL") 16 | CleanUp = os.Getenv("CLEANUP") 17 | ) 18 | -------------------------------------------------------------------------------- /test/e2e/framework/scaletest/templates/networkpolicy.go: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | netv1 "k8s.io/api/networking/v1" 5 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 6 | ) 7 | 8 | var ( 9 | NetworkPolicy = netv1.NetworkPolicy{ 10 | TypeMeta: metav1.TypeMeta{ 11 | Kind: "NetworkPolicy", 12 | APIVersion: "networking.k8s.io/v1", 13 | }, 14 | ObjectMeta: metav1.ObjectMeta{ 15 | Name: "template-network-policy", 16 | }, 17 | Spec: netv1.NetworkPolicySpec{ 18 | PolicyTypes: []netv1.PolicyType{ 19 | "Ingress", 20 | "Egress", 21 | }, 22 | PodSelector: metav1.LabelSelector{ 23 | MatchLabels: map[string]string{}, 24 | }, 25 | }, 26 | } 27 | ) 28 | -------------------------------------------------------------------------------- /test/e2e/framework/types/runner.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | // A wrapper around a job, so that internal job components don't require things like *testing.T 11 | // and can be reused elsewhere 12 | type Runner struct { 13 | t *testing.T 14 | Job *Job 15 | } 16 | 17 | func NewRunner(t *testing.T, job *Job) *Runner { 18 | return &Runner{ 19 | t: t, 20 | Job: job, 21 | } 22 | } 23 | 24 | func (r *Runner) Run(ctx context.Context) { 25 | if r.t.Failed() { 26 | return 27 | } 28 | runComplete := make(chan error) 29 | 30 | go func() { 31 | runComplete <- r.Job.Run() 32 | close(runComplete) 33 | }() 34 | select { 35 | case <-ctx.Done(): 36 | r.t.Fatal("Failed to complete execution:", ctx.Err()) 37 | case err := <-runComplete: 38 | require.NoError(r.t, err) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/e2e/framework/types/step_sleep.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "log" 5 | "time" 6 | ) 7 | 8 | type Sleep struct { 9 | Duration time.Duration 10 | } 11 | 12 | func (c *Sleep) Run() error { 13 | log.Printf("sleeping for %s...\n", c.Duration.String()) 14 | time.Sleep(c.Duration) 15 | return nil 16 | } 17 | 18 | func (c *Sleep) Stop() error { 19 | return nil 20 | } 21 | 22 | func (c *Sleep) Prevalidate() error { 23 | return nil 24 | } 25 | -------------------------------------------------------------------------------- /test/e2e/framework/types/step_stop.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "reflect" 7 | ) 8 | 9 | type Stop struct { 10 | BackgroundID string 11 | Step Step 12 | } 13 | 14 | func (c *Stop) Run() error { 15 | stepName := reflect.TypeOf(c.Step).Elem().Name() 16 | log.Println("stopping step:", stepName) 17 | err := c.Step.Stop() 18 | if err != nil { 19 | return fmt.Errorf("failed to stop step: %s with err %w", stepName, err) 20 | } 21 | return nil 22 | } 23 | 24 | func (c *Stop) Stop() error { 25 | return nil 26 | } 27 | 28 | func (c *Stop) Prevalidate() error { 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /test/e2e/scenarios/windows/scenario.go: -------------------------------------------------------------------------------- 1 | package windows 2 | 3 | import ( 4 | "github.com/microsoft/retina/test/e2e/common" 5 | "github.com/microsoft/retina/test/e2e/framework/types" 6 | ) 7 | 8 | func ValidateWindowsBasicMetric() *types.Scenario { 9 | name := "Windows Metrics" 10 | steps := []*types.StepWrapper{ 11 | { 12 | Step: &ValidateHNSMetric{ 13 | KubeConfigFilePath: "./test.pem", 14 | RetinaDaemonSetNamespace: common.KubeSystemNamespace, 15 | RetinaDaemonSetName: "retina-agent-win", 16 | }, 17 | }, 18 | } 19 | return types.NewScenario(name, steps...) 20 | } 21 | -------------------------------------------------------------------------------- /test/enricher/enricher: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/test/enricher/enricher -------------------------------------------------------------------------------- /test/goldpinger/cluster-role-binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: goldpinger-clusterrolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: goldpinger-clusterrole 9 | subjects: 10 | - kind: ServiceAccount 11 | name: goldpinger-serviceaccount 12 | namespace: default 13 | -------------------------------------------------------------------------------- /test/goldpinger/cluster-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: goldpinger-clusterrole 5 | rules: 6 | - apiGroups: 7 | - "" 8 | resources: 9 | - pods 10 | verbs: 11 | - list 12 | -------------------------------------------------------------------------------- /test/goldpinger/goldpinger-deny-all.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: NetworkPolicy 3 | metadata: 4 | name: goldpinger-deny-all 5 | namespace: default 6 | spec: 7 | podSelector: 8 | matchLabels: 9 | app: goldpinger 10 | policyTypes: 11 | - Egress 12 | status: {} 13 | -------------------------------------------------------------------------------- /test/goldpinger/service-account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: goldpinger-serviceaccount 5 | namespace: default 6 | -------------------------------------------------------------------------------- /test/goldpinger/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: goldpinger 5 | namespace: default 6 | labels: 7 | app: goldpinger 8 | spec: 9 | type: NodePort 10 | ports: 11 | - port: 8080 12 | nodePort: 30080 13 | name: http 14 | selector: 15 | app: goldpinger 16 | -------------------------------------------------------------------------------- /test/image/.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore build and test binaries. 3 | bin/ 4 | testbin/ 5 | -------------------------------------------------------------------------------- /test/image/Dockerfile: -------------------------------------------------------------------------------- 1 | # build stage 2 | # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" 3 | FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:5341a0010ecff114ee2f11f5eaa4f73b721b54142954041523f3e785d5c4b978 AS builder 4 | ENV CGO_ENABLED=0 5 | COPY . /go/src/github.com/microsoft/retina 6 | WORKDIR /go/src/github.com/microsoft/retina 7 | RUN tdnf install -y clang16 lld16 bpftool libbpf-devel make git jq 8 | RUN go generate /go/src/github.com/microsoft/retina/pkg/plugin/... 9 | # RUN go mod edit -module retina 10 | # RUN make all generate 11 | #RUN go generate ./... 12 | RUN make test 13 | #RUN go test -covermode count -coverprofile /home/runner/work/_temp/go.cov -coverpkg ./... ./... 14 | RUN cat coverage.out 15 | 16 | FROM scratch AS artifacts 17 | COPY --from=builder /go/src/github.com/microsoft/retina/coverage.out /coverage.out 18 | -------------------------------------------------------------------------------- /test/kind/kind.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | networking: 4 | apiServerAddress: "0.0.0.0" 5 | nodes: 6 | - role: control-plane 7 | image: kindest/node:v1.25.3 8 | - role: worker 9 | image: kindest/node:v1.25.3 10 | - role: worker 11 | image: kindest/node:v1.25.3 12 | -------------------------------------------------------------------------------- /test/multicloud/.gitignore: -------------------------------------------------------------------------------- 1 | terraform.tfvars 2 | .terraform 3 | terraform.tfstate 4 | *terraform.tfstate.* 5 | service-key.json 6 | *-kind-config 7 | retina-capture/* -------------------------------------------------------------------------------- /test/multicloud/diagrams/mc-eks-grafana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/test/multicloud/diagrams/mc-eks-grafana.png -------------------------------------------------------------------------------- /test/multicloud/diagrams/mc-gke-hubble-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/test/multicloud/diagrams/mc-gke-hubble-ui.png -------------------------------------------------------------------------------- /test/multicloud/diagrams/mc-gke-hubble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/test/multicloud/diagrams/mc-gke-hubble.png -------------------------------------------------------------------------------- /test/multicloud/examples/aks/main.tf: -------------------------------------------------------------------------------- 1 | module "aks" { 2 | source = "../../modules/aks" 3 | location = var.location 4 | resource_group_name = var.resource_group_name 5 | prefix = var.prefix 6 | labels = var.labels 7 | } 8 | 9 | output "kubeconfig" { 10 | value = module.aks.azure_get_kubeconfig 11 | sensitive = true 12 | } 13 | -------------------------------------------------------------------------------- /test/multicloud/examples/aks/outputs.tf: -------------------------------------------------------------------------------- 1 | output "host" { 2 | value = module.aks.host 3 | sensitive = true 4 | } 5 | 6 | output "client_certificate" { 7 | value = module.aks.client_certificate 8 | sensitive = true 9 | } 10 | 11 | output "client_key" { 12 | value = module.aks.client_key 13 | sensitive = true 14 | } 15 | 16 | output "cluster_ca_certificate" { 17 | value = module.aks.cluster_ca_certificate 18 | sensitive = true 19 | } -------------------------------------------------------------------------------- /test/multicloud/examples/aks/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "1.8.3" 3 | required_providers { 4 | azurerm = { 5 | source = "hashicorp/azurerm" 6 | version = "4.15.0" 7 | } 8 | } 9 | } 10 | 11 | # Initialize the Azure provider 12 | provider "azurerm" { 13 | features { 14 | resource_group { 15 | prevent_deletion_if_contains_resources = false 16 | } 17 | } 18 | subscription_id = var.subscription_id 19 | tenant_id = var.tenant_id 20 | } 21 | -------------------------------------------------------------------------------- /test/multicloud/examples/aks/variables.tf: -------------------------------------------------------------------------------- 1 | variable "subscription_id" { 2 | description = "The subscription ID for the Azure account." 3 | type = string 4 | } 5 | 6 | variable "tenant_id" { 7 | description = "The tenant ID for the Azure account." 8 | type = string 9 | } 10 | 11 | variable "location" { 12 | description = "The Azure Cloud location where AKS will be deployed to." 13 | type = string 14 | default = "UK South" 15 | } 16 | 17 | variable "resource_group_name" { 18 | description = "The name of the resource group." 19 | type = string 20 | default = "example-rg" 21 | } 22 | 23 | variable "prefix" { 24 | description = "A prefix to add to all resources." 25 | type = string 26 | default = "example-mc" 27 | } 28 | 29 | variable "labels" { 30 | description = "A map of labels to add to all resources." 31 | type = map(string) 32 | default = {} 33 | } 34 | -------------------------------------------------------------------------------- /test/multicloud/examples/eks/main.tf: -------------------------------------------------------------------------------- 1 | module "eks" { 2 | source = "../../modules/eks" 3 | prefix = var.prefix 4 | region = var.region 5 | } -------------------------------------------------------------------------------- /test/multicloud/examples/eks/outputs.tf: -------------------------------------------------------------------------------- 1 | output "aws_get_kubeconfig" { 2 | value = module.eks.aws_get_kubeconfig 3 | description = "Run this command to fetch the kubeconfig for your EKS cluster" 4 | } 5 | 6 | output "access_token" { 7 | value = module.eks.access_token 8 | sensitive = true 9 | } 10 | 11 | output "host" { 12 | value = module.eks.host 13 | sensitive = true 14 | } 15 | 16 | output "cluster_ca_certificate" { 17 | value = module.eks.cluster_ca_certificate 18 | sensitive = true 19 | } -------------------------------------------------------------------------------- /test/multicloud/examples/eks/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | source = "hashicorp/aws" 5 | version = "5.88.0" 6 | } 7 | } 8 | } 9 | 10 | # Configure the AWS Provider 11 | provider "aws" { 12 | region = var.region 13 | } 14 | -------------------------------------------------------------------------------- /test/multicloud/examples/eks/variables.tf: -------------------------------------------------------------------------------- 1 | variable "prefix" { 2 | description = "A prefix to add to all resources." 3 | type = string 4 | } 5 | 6 | variable "region" { 7 | description = "The AWS region to deploy to." 8 | type = string 9 | } -------------------------------------------------------------------------------- /test/multicloud/examples/gke/main.tf: -------------------------------------------------------------------------------- 1 | module "gke" { 2 | source = "../../modules/gke" 3 | location = var.location 4 | prefix = var.prefix 5 | project = var.project 6 | machine_type = var.machine_type 7 | } 8 | 9 | data "google_client_config" "current" {} -------------------------------------------------------------------------------- /test/multicloud/examples/gke/outputs.tf: -------------------------------------------------------------------------------- 1 | output "host" { 2 | value = module.gke.host 3 | sensitive = true 4 | } 5 | 6 | output "cluster_ca_certificate" { 7 | value = module.gke.cluster_ca_certificate 8 | sensitive = true 9 | } 10 | 11 | output "access_token" { 12 | value = data.google_client_config.current.access_token 13 | sensitive = true 14 | } -------------------------------------------------------------------------------- /test/multicloud/examples/gke/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "1.8.3" 3 | required_providers { 4 | google = { 5 | source = "hashicorp/google" 6 | version = "6.17.0" 7 | } 8 | } 9 | } 10 | 11 | # Initialize the Google provider 12 | provider "google" { 13 | project = var.project 14 | region = var.location 15 | } 16 | -------------------------------------------------------------------------------- /test/multicloud/examples/gke/variables.tf: -------------------------------------------------------------------------------- 1 | variable "project" { 2 | description = "The Google Cloud project where resources will be deployed." 3 | type = string 4 | } 5 | 6 | variable "location" { 7 | description = "The Google Cloud location where GKE will be deployed to." 8 | type = string 9 | } 10 | 11 | variable "prefix" { 12 | description = "A prefix to add to all resources." 13 | type = string 14 | } 15 | 16 | variable "machine_type" { 17 | description = "The machine type to use for the GKE nodes." 18 | type = string 19 | } 20 | -------------------------------------------------------------------------------- /test/multicloud/examples/grafana/main.tf: -------------------------------------------------------------------------------- 1 | module "grafana" { 2 | source = "../../modules/grafana" 3 | prometheus_endpoints = { 4 | # This is obviously wrong, but it's just an example 5 | # and you can check on GrafanaCloud to validate the 6 | # data source was created 7 | some = "http://example.com:1234" 8 | } 9 | } -------------------------------------------------------------------------------- /test/multicloud/examples/grafana/providers.tf: -------------------------------------------------------------------------------- 1 | # Terraform Grafana provider configuration 2 | terraform { 3 | required_version = "1.8.3" 4 | required_providers { 5 | grafana = { 6 | source = "grafana/grafana" 7 | version = "3.18.3" 8 | } 9 | } 10 | } 11 | 12 | # Initialize the Grafana provider 13 | provider "grafana" { 14 | url = var.grafana_url 15 | } -------------------------------------------------------------------------------- /test/multicloud/examples/grafana/variables.tf: -------------------------------------------------------------------------------- 1 | variable "grafana_url" { 2 | description = "The URL of the Grafana instance" 3 | type = string 4 | } 5 | -------------------------------------------------------------------------------- /test/multicloud/examples/integration/prometheus-kind/main.tf: -------------------------------------------------------------------------------- 1 | module "kind" { 2 | source = "../../../modules/kind" 3 | prefix = var.prefix 4 | } 5 | 6 | module "retina" { 7 | depends_on = [module.kind] 8 | source = "../../../modules/helm-release" 9 | release_name = var.retina_release_name 10 | repository_url = var.retina_repository_url 11 | chart_version = var.retina_chart_version 12 | chart_name = var.retina_chart_name 13 | values = var.retina_values 14 | } 15 | 16 | module "prometheus" { 17 | depends_on = [ 18 | module.kind, 19 | module.retina 20 | ] 21 | source = "../../../modules/helm-release" 22 | release_name = var.prometheus_release_name 23 | repository_url = var.prometheus_repository_url 24 | chart_version = var.prometheus_chart_version 25 | chart_name = var.prometheus_chart_name 26 | values = var.prometheus_values 27 | } 28 | -------------------------------------------------------------------------------- /test/multicloud/examples/integration/prometheus-kind/outputs.tf: -------------------------------------------------------------------------------- 1 | output "host" { 2 | value = module.kind.host 3 | sensitive = true 4 | } 5 | 6 | output "cluster_ca_certificate" { 7 | value = module.kind.cluster_ca_certificate 8 | sensitive = true 9 | } 10 | 11 | output "client_certificate" { 12 | value = module.kind.client_certificate 13 | sensitive = true 14 | } 15 | 16 | output "client_key" { 17 | value = module.kind.client_key 18 | sensitive = true 19 | } 20 | -------------------------------------------------------------------------------- /test/multicloud/examples/integration/prometheus-kind/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "1.8.3" 3 | required_providers { 4 | kind = { 5 | source = "tehcyx/kind" 6 | version = "0.7.0" 7 | } 8 | helm = { 9 | source = "hashicorp/helm" 10 | version = "2.17.0" 11 | } 12 | } 13 | } 14 | 15 | # Initialize the kind provider 16 | provider "kind" {} 17 | 18 | # Initialize the Helm provider 19 | provider "helm" { 20 | kubernetes { 21 | host = module.kind.host 22 | client_certificate = module.kind.client_certificate 23 | client_key = module.kind.client_key 24 | cluster_ca_certificate = module.kind.cluster_ca_certificate 25 | } 26 | } -------------------------------------------------------------------------------- /test/multicloud/examples/integration/retina-aks/main.tf: -------------------------------------------------------------------------------- 1 | module "aks" { 2 | source = "../../../modules/aks" 3 | location = var.location 4 | resource_group_name = var.resource_group_name 5 | prefix = var.prefix 6 | labels = var.labels 7 | } 8 | 9 | module "retina" { 10 | depends_on = [module.aks] 11 | source = "../../../modules/helm-release" 12 | release_name = var.retina_release_name 13 | repository_url = var.retina_repository_url 14 | chart_version = var.retina_chart_version 15 | chart_name = var.retina_chart_name 16 | values = var.retina_values 17 | } 18 | -------------------------------------------------------------------------------- /test/multicloud/examples/integration/retina-aks/outputs.tf: -------------------------------------------------------------------------------- 1 | output "host" { 2 | value = module.aks.host 3 | sensitive = true 4 | } 5 | 6 | output "client_certificate" { 7 | value = module.aks.client_certificate 8 | sensitive = true 9 | } 10 | 11 | output "client_key" { 12 | value = module.aks.client_key 13 | sensitive = true 14 | } 15 | 16 | output "cluster_ca_certificate" { 17 | value = module.aks.cluster_ca_certificate 18 | sensitive = true 19 | } -------------------------------------------------------------------------------- /test/multicloud/examples/integration/retina-aks/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "1.8.3" 3 | required_providers { 4 | azurerm = { 5 | source = "hashicorp/azurerm" 6 | version = "4.15.0" 7 | } 8 | helm = { 9 | source = "hashicorp/helm" 10 | version = "2.17.0" 11 | } 12 | } 13 | } 14 | 15 | # Initialize the Azure provider 16 | provider "azurerm" { 17 | features { 18 | resource_group { 19 | prevent_deletion_if_contains_resources = false 20 | } 21 | } 22 | subscription_id = var.subscription_id 23 | tenant_id = var.tenant_id 24 | } 25 | 26 | provider "helm" { 27 | kubernetes { 28 | host = module.aks.host 29 | client_certificate = base64decode(module.aks.client_certificate) 30 | client_key = base64decode(module.aks.client_key) 31 | cluster_ca_certificate = base64decode(module.aks.cluster_ca_certificate) 32 | } 33 | } -------------------------------------------------------------------------------- /test/multicloud/examples/integration/retina-eks/main.tf: -------------------------------------------------------------------------------- 1 | module "eks" { 2 | source = "../../../modules/eks" 3 | prefix = var.prefix 4 | region = var.region 5 | } 6 | 7 | module "retina" { 8 | depends_on = [module.eks] 9 | source = "../../../modules/helm-release" 10 | release_name = var.retina_release_name 11 | repository_url = var.retina_repository_url 12 | chart_version = var.retina_chart_version 13 | chart_name = var.retina_chart_name 14 | values = var.retina_values 15 | } 16 | -------------------------------------------------------------------------------- /test/multicloud/examples/integration/retina-eks/outputs.tf: -------------------------------------------------------------------------------- 1 | output "access_token" { 2 | value = module.eks.access_token 3 | sensitive = true 4 | } 5 | 6 | output "host" { 7 | value = module.eks.host 8 | sensitive = true 9 | } 10 | 11 | output "cluster_ca_certificate" { 12 | value = module.eks.cluster_ca_certificate 13 | sensitive = true 14 | } -------------------------------------------------------------------------------- /test/multicloud/examples/integration/retina-eks/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "1.8.3" 3 | required_providers { 4 | aws = { 5 | source = "hashicorp/aws" 6 | version = "5.88.0" 7 | } 8 | helm = { 9 | source = "hashicorp/helm" 10 | version = "2.17.0" 11 | } 12 | } 13 | } 14 | 15 | # Configure the AWS Provider 16 | provider "aws" { 17 | region = var.region 18 | } 19 | 20 | data "aws_eks_cluster_auth" "eks" { 21 | name = "${var.prefix}-eks" 22 | depends_on = [module.eks] 23 | } 24 | 25 | data "aws_eks_cluster" "eks" { 26 | name = "${var.prefix}-eks" 27 | depends_on = [module.eks] 28 | } 29 | 30 | # Initialize the Helm provider 31 | provider "helm" { 32 | kubernetes { 33 | token = data.aws_eks_cluster_auth.eks.token 34 | host = data.aws_eks_cluster.eks.endpoint 35 | cluster_ca_certificate = base64decode(data.aws_eks_cluster.eks.certificate_authority[0].data) 36 | } 37 | } -------------------------------------------------------------------------------- /test/multicloud/examples/integration/retina-gke/main.tf: -------------------------------------------------------------------------------- 1 | module "gke" { 2 | source = "../../../modules/gke" 3 | location = var.location 4 | prefix = var.prefix 5 | project = var.project 6 | machine_type = var.machine_type 7 | } 8 | 9 | module "retina" { 10 | depends_on = [module.gke] 11 | source = "../../../modules/helm-release" 12 | release_name = var.retina_release_name 13 | repository_url = var.retina_repository_url 14 | chart_version = var.retina_chart_version 15 | chart_name = var.retina_chart_name 16 | values = var.retina_values 17 | } 18 | -------------------------------------------------------------------------------- /test/multicloud/examples/integration/retina-gke/outputs.tf: -------------------------------------------------------------------------------- 1 | output "host" { 2 | value = module.gke.host 3 | sensitive = true 4 | } 5 | 6 | output "cluster_ca_certificate" { 7 | value = module.gke.cluster_ca_certificate 8 | sensitive = true 9 | } 10 | 11 | output "access_token" { 12 | value = data.google_client_config.current.access_token 13 | sensitive = true 14 | } 15 | -------------------------------------------------------------------------------- /test/multicloud/examples/integration/retina-gke/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "1.8.3" 3 | required_providers { 4 | google = { 5 | source = "hashicorp/google" 6 | version = "6.17.0" 7 | } 8 | helm = { 9 | source = "hashicorp/helm" 10 | version = "2.17.0" 11 | } 12 | } 13 | } 14 | 15 | # Initialize the Google provider 16 | provider "google" { 17 | project = var.project 18 | region = var.location 19 | } 20 | 21 | data "google_client_config" "current" {} 22 | 23 | # Initialize the Helm provider 24 | provider "helm" { 25 | kubernetes { 26 | token = data.google_client_config.current.access_token 27 | host = module.gke.host 28 | cluster_ca_certificate = base64decode(module.gke.cluster_ca_certificate) 29 | } 30 | } -------------------------------------------------------------------------------- /test/multicloud/examples/integration/retina-kind/main.tf: -------------------------------------------------------------------------------- 1 | module "kind" { 2 | source = "../../../modules/kind" 3 | prefix = var.prefix 4 | } 5 | 6 | module "retina" { 7 | depends_on = [module.kind] 8 | source = "../../../modules/helm-release" 9 | release_name = var.retina_release_name 10 | repository_url = var.retina_repository_url 11 | chart_version = var.retina_chart_version 12 | chart_name = var.retina_chart_name 13 | values = var.retina_values 14 | } 15 | -------------------------------------------------------------------------------- /test/multicloud/examples/integration/retina-kind/outputs.tf: -------------------------------------------------------------------------------- 1 | output "host" { 2 | value = module.kind.host 3 | sensitive = true 4 | } 5 | 6 | output "cluster_ca_certificate" { 7 | value = module.kind.cluster_ca_certificate 8 | sensitive = true 9 | } 10 | 11 | output "client_certificate" { 12 | value = module.kind.client_certificate 13 | sensitive = true 14 | } 15 | 16 | output "client_key" { 17 | value = module.kind.client_key 18 | sensitive = true 19 | } 20 | -------------------------------------------------------------------------------- /test/multicloud/examples/integration/retina-kind/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "1.8.3" 3 | required_providers { 4 | kind = { 5 | source = "tehcyx/kind" 6 | version = "0.7.0" 7 | } 8 | helm = { 9 | source = "hashicorp/helm" 10 | version = "2.17.0" 11 | } 12 | } 13 | } 14 | 15 | # Initialize the kind provider 16 | provider "kind" {} 17 | 18 | # Initialize the Helm provider 19 | provider "helm" { 20 | kubernetes { 21 | host = module.kind.host 22 | client_certificate = module.kind.client_certificate 23 | client_key = module.kind.client_key 24 | cluster_ca_certificate = module.kind.cluster_ca_certificate 25 | } 26 | } -------------------------------------------------------------------------------- /test/multicloud/examples/integration/retina-kind/variables.tf: -------------------------------------------------------------------------------- 1 | variable "prefix" { 2 | description = "A prefix to add to all resources." 3 | type = string 4 | default = "mc" 5 | } 6 | 7 | variable "retina_release_name" { 8 | description = "The name of the Helm release." 9 | type = string 10 | default = "retina" 11 | } 12 | 13 | variable "retina_repository_url" { 14 | description = "The URL of the Helm repository." 15 | type = string 16 | default = "oci://ghcr.io/microsoft/retina/charts" 17 | } 18 | 19 | variable "retina_chart_version" { 20 | description = "The version of the Helm chart to install." 21 | type = string 22 | default = "v0.0.24" 23 | } 24 | 25 | variable "retina_chart_name" { 26 | description = "The name of the Helm chart to install." 27 | type = string 28 | default = "retina" 29 | } 30 | 31 | variable "retina_values" { 32 | description = "This corresponds to Helm values.yaml" 33 | type = any 34 | } 35 | -------------------------------------------------------------------------------- /test/multicloud/examples/kind/.terraform.lock.hcl: -------------------------------------------------------------------------------- 1 | # This file is maintained automatically by "tofu init". 2 | # Manual edits may be lost in future updates. 3 | 4 | provider "registry.opentofu.org/tehcyx/kind" { 5 | version = "0.7.0" 6 | constraints = "0.7.0" 7 | hashes = [ 8 | "h1:nFhFHmE5+dCd9S9dEMwnMNWzyxoVipYobkhXYoDbhgA=", 9 | "zh:171a2fb0137bfbdebd56cd65afd2e0e2167315fe4cb6a07a218db40cb17339c3", 10 | "zh:3260b078b7997ddfd03845326ffaeed7f678eeaaf7918430356f22e299e36f22", 11 | "zh:4066ab3feb482a0dd1bfff6590d89a0ec30478f63c9d8253cfdadb4b8db2234d", 12 | "zh:537af73261d53f4840d1f89d8e5835c52ddb97102e6314f6aea9b8e49c43d610", 13 | "zh:d63e94d828ba0339600d992b0a6695cff939b0aaac1c39b31d38e3c4f3823674", 14 | "zh:f971c617bf6b37d07a5042f13a9ab02b42d0ceb14934174eecc81abeec233c40", 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /test/multicloud/examples/kind/main.tf: -------------------------------------------------------------------------------- 1 | module "kind" { 2 | source = "../../modules/kind" 3 | prefix = var.prefix 4 | } -------------------------------------------------------------------------------- /test/multicloud/examples/kind/outputs.tf: -------------------------------------------------------------------------------- 1 | output "host" { 2 | value = module.kind.host 3 | sensitive = true 4 | } 5 | 6 | output "cluster_ca_certificate" { 7 | value = module.kind.cluster_ca_certificate 8 | sensitive = true 9 | } 10 | 11 | output "client_certificate" { 12 | value = module.kind.client_certificate 13 | sensitive = true 14 | } 15 | 16 | output "client_key" { 17 | value = module.kind.client_key 18 | sensitive = true 19 | } 20 | -------------------------------------------------------------------------------- /test/multicloud/examples/kind/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "1.8.3" 3 | required_providers { 4 | kind = { 5 | source = "tehcyx/kind" 6 | version = "0.7.0" 7 | } 8 | } 9 | } 10 | 11 | # Initialize the kind provider 12 | provider "kind" {} 13 | -------------------------------------------------------------------------------- /test/multicloud/examples/kind/variables.tf: -------------------------------------------------------------------------------- 1 | variable "prefix" { 2 | description = "A prefix to add to all resources." 3 | type = string 4 | } -------------------------------------------------------------------------------- /test/multicloud/live/files/retina-hubble.yaml: -------------------------------------------------------------------------------- 1 | # hubble control-plane 2 | operator: 3 | enabled: true 4 | tag: v0.0.29 5 | repository: ghcr.io/microsoft/retina/retina-operator 6 | enableRetinaEndpoint: true 7 | 8 | agent: 9 | enabled: true 10 | repository: ghcr.io/microsoft/retina/retina-agent 11 | tag: v0.0.29 12 | 13 | init: 14 | enabled: true 15 | repository: ghcr.io/microsoft/retina/retina-init 16 | tag: v0.0.29 17 | 18 | hubble: 19 | relay: 20 | tls: 21 | server: 22 | enabled: false 23 | tls: 24 | enabled: false 25 | auto: 26 | enabled: false 27 | method: cronJob 28 | certValidityDuration: 1 29 | schedule: "*/10 * * * *" # every 10 minutes 30 | 31 | enabledPlugin_linux: '["packetparser","dropreason","packetforward","linuxutil","dns"]' 32 | -------------------------------------------------------------------------------- /test/multicloud/live/files/retina-standard-advanced-local-operator.yaml: -------------------------------------------------------------------------------- 1 | # advanced/pod-level mode designed for scale 2 | # metrics are aggregated by "local" Pod (source for outgoing traffic, destination for incoming traffic) 3 | image: 4 | repository: ghcr.io/microsoft/retina/retina-agent 5 | initRepository: ghcr.io/microsoft/retina/retina-init 6 | tag: v0.0.24 7 | 8 | operator: 9 | enabled: true 10 | enableRetinaEndpoint: true 11 | tag: v0.0.24 12 | repository: ghcr.io/microsoft/retina/retina-operator 13 | 14 | enabledPlugin_linux: '["packetparser","dropreason","packetforward","linuxutil","dns"]' 15 | enablePodLevel: true 16 | enableAnnotations: true 17 | -------------------------------------------------------------------------------- /test/multicloud/live/files/retina-standard-advanced-remote-operator.yaml: -------------------------------------------------------------------------------- 1 | # advanced/pod-level mode with scale limitations 2 | # metrics are aggregated by source and destination Pod 3 | image: 4 | repository: ghcr.io/microsoft/retina/retina-agent 5 | initRepository: ghcr.io/microsoft/retina/retina-init 6 | tag: v0.0.24 7 | 8 | operator: 9 | enabled: true 10 | enableRetinaEndpoint: true 11 | tag: v0.0.24 12 | repository: ghcr.io/microsoft/retina/retina-operator 13 | 14 | enabledPlugin_linux: '["packetparser","dropreason","packetforward","linuxutil","dns"]' 15 | enablePodLevel: true 16 | enableAnnotations: true 17 | remoteContext: true 18 | -------------------------------------------------------------------------------- /test/multicloud/live/files/retina-standard-basic-mode.yaml: -------------------------------------------------------------------------------- 1 | # basic/node-level mode 2 | image: 3 | rag: v0.0.24 4 | operator: 5 | tag: v0.0.24 6 | enabledPlugin_linux: '["dropreason","packetforward","linuxutil","dns"]' 7 | -------------------------------------------------------------------------------- /test/multicloud/live/retina-aks/outputs.tf: -------------------------------------------------------------------------------- 1 | output "kubeconfig_command" { 2 | value = module.aks.azure_get_kubeconfig 3 | } 4 | 5 | output "cluster_name" { 6 | value = module.aks.cluster_name 7 | } 8 | -------------------------------------------------------------------------------- /test/multicloud/live/retina-aks/variables.tf: -------------------------------------------------------------------------------- 1 | variable "subscription_id" { 2 | description = "The subscription ID for the Azure account." 3 | type = string 4 | } 5 | 6 | variable "tenant_id" { 7 | description = "The tenant ID for the Azure account." 8 | type = string 9 | } 10 | 11 | variable "grafana_url" { 12 | description = "The URL of the Grafana instance" 13 | type = string 14 | } 15 | 16 | variable "grafana_cloud_access_policy_token" { 17 | description = "The Cloud Access Policy token required for Grafana Cloud API operations" 18 | type = string 19 | sensitive = true 20 | } 21 | 22 | variable "grafana_pdc_hosted_grafana_id" { 23 | description = "The hosted Grafana ID for the Grafana PDC agent." 24 | type = string 25 | } 26 | 27 | variable "grafana_pdc_cluster" { 28 | description = "The cluster name for the Grafana PDC agent." 29 | type = string 30 | } -------------------------------------------------------------------------------- /test/multicloud/live/retina-eks/locals.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | prefix = "mc" 3 | region = "eu-west-1" 4 | 5 | retina_release_name = "retina" 6 | retina_repository_url = "oci://ghcr.io/microsoft/retina/charts" 7 | retina_chart_version = "v0.0.29" 8 | retina_release_namespace = "kube-system" 9 | retina_chart_name = "retina-hubble" 10 | retina_values = yamldecode(file("../files/retina-hubble.yaml")) 11 | 12 | prometheus_release_name = "prometheus" 13 | prometheus_repository_url = "https://prometheus-community.github.io/helm-charts" 14 | prometheus_chart_version = "68.4.3" 15 | prometheus_chart_name = "kube-prometheus-stack" 16 | prometheus_release_namespace = "kube-system" 17 | prometheus_values = yamldecode(file("../../../../deploy/hubble/prometheus/values.yaml")) 18 | cluster_name = "ElasticKubernetesService" 19 | 20 | # All dashboards are deployed as part of live/retina-aks 21 | dashboards = {} 22 | } -------------------------------------------------------------------------------- /test/multicloud/live/retina-eks/outputs.tf: -------------------------------------------------------------------------------- 1 | output "kubeconfig_command" { 2 | value = module.eks.aws_get_kubeconfig 3 | } 4 | 5 | output "cluster_name" { 6 | value = module.eks.cluster_name 7 | } -------------------------------------------------------------------------------- /test/multicloud/live/retina-eks/variables.tf: -------------------------------------------------------------------------------- 1 | variable "grafana_url" { 2 | description = "The URL of the Grafana instance" 3 | type = string 4 | } 5 | 6 | variable "grafana_cloud_access_policy_token" { 7 | description = "The Cloud Access Policy token required for Grafana Cloud API operations" 8 | type = string 9 | sensitive = true 10 | } 11 | 12 | variable "grafana_pdc_hosted_grafana_id" { 13 | description = "The hosted Grafana ID for the Grafana PDC agent." 14 | type = string 15 | } 16 | 17 | variable "grafana_pdc_cluster" { 18 | description = "The cluster name for the Grafana PDC agent." 19 | type = string 20 | } -------------------------------------------------------------------------------- /test/multicloud/live/retina-gke/outputs.tf: -------------------------------------------------------------------------------- 1 | output "kubeconfig_command" { 2 | value = module.gke.gcloud_get_kubeconfig 3 | } 4 | 5 | output "cluster_name" { 6 | value = module.gke.cluster_name 7 | } -------------------------------------------------------------------------------- /test/multicloud/live/retina-gke/variables.tf: -------------------------------------------------------------------------------- 1 | variable "project" { 2 | description = "Project ID" 3 | type = string 4 | } 5 | 6 | variable "grafana_url" { 7 | description = "The URL of the Grafana instance" 8 | type = string 9 | } 10 | 11 | variable "grafana_cloud_access_policy_token" { 12 | description = "The Cloud Access Policy token required for Grafana Cloud API operations" 13 | type = string 14 | sensitive = true 15 | } 16 | 17 | variable "grafana_pdc_hosted_grafana_id" { 18 | description = "The hosted Grafana ID for the Grafana PDC agent." 19 | type = string 20 | } 21 | 22 | variable "grafana_pdc_cluster" { 23 | description = "The cluster name for the Grafana PDC agent." 24 | type = string 25 | } -------------------------------------------------------------------------------- /test/multicloud/live/retina-kind/locals.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | prefix = "mc" 3 | 4 | retina_release_name = "retina" 5 | retina_release_namespace = "kube-system" 6 | retina_repository_url = "oci://ghcr.io/microsoft/retina/charts" 7 | retina_chart_version = "v0.0.24" 8 | retina_chart_name = "retina" 9 | retina_values = yamldecode(file("../files/retina-standard-advanced-remote-operator.yaml")) 10 | 11 | prometheus_release_name = "prometheus" 12 | prometheus_release_namespace = "kube-system" 13 | prometheus_repository_url = "https://prometheus-community.github.io/helm-charts" 14 | prometheus_chart_version = "68.4.3" 15 | prometheus_chart_name = "kube-prometheus-stack" 16 | prometheus_values = yamldecode(file("../../../../deploy/standard/prometheus/values.yaml")) 17 | } -------------------------------------------------------------------------------- /test/multicloud/live/retina-kind/main.tf: -------------------------------------------------------------------------------- 1 | module "kind" { 2 | source = "../../modules/kind" 3 | prefix = local.prefix 4 | } 5 | 6 | module "retina_kind" { 7 | depends_on = [module.kind] 8 | source = "../../modules/helm-release" 9 | chart_version = local.retina_chart_version 10 | release_name = local.retina_release_name 11 | release_namespace = local.retina_release_namespace 12 | repository_url = local.retina_repository_url 13 | chart_name = local.retina_chart_name 14 | values = local.retina_values 15 | } 16 | 17 | module "prometheus_kind" { 18 | depends_on = [module.kind] 19 | source = "../../modules/helm-release" 20 | chart_version = local.prometheus_chart_version 21 | values = local.prometheus_values 22 | release_name = local.prometheus_release_name 23 | release_namespace = local.prometheus_release_namespace 24 | repository_url = local.prometheus_repository_url 25 | chart_name = local.prometheus_chart_name 26 | } 27 | -------------------------------------------------------------------------------- /test/multicloud/live/retina-kind/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "1.8.3" 3 | required_providers { 4 | kind = { 5 | source = "tehcyx/kind" 6 | version = "0.7.0" 7 | } 8 | helm = { 9 | source = "hashicorp/helm" 10 | version = "2.17.0" 11 | } 12 | } 13 | } 14 | 15 | # Initialize the kind provider 16 | provider "kind" {} 17 | 18 | # Initialize the Helm provider 19 | provider "helm" { 20 | kubernetes { 21 | host = module.kind.host 22 | client_certificate = module.kind.client_certificate 23 | client_key = module.kind.client_key 24 | cluster_ca_certificate = module.kind.cluster_ca_certificate 25 | } 26 | } -------------------------------------------------------------------------------- /test/multicloud/modules/aks/outputs.tf: -------------------------------------------------------------------------------- 1 | output "azure_get_kubeconfig" { 2 | value = "az aks get-credentials --resource-group ${azurerm_resource_group.aks_rg.name} --name ${azurerm_kubernetes_cluster.aks.name} --admin" 3 | description = "Run this command to fetch the kubeconfig for your AKS cluster" 4 | } 5 | 6 | output "cluster_name" { 7 | value = azurerm_kubernetes_cluster.aks.name 8 | description = "AKS cluster name" 9 | } 10 | 11 | output "host" { 12 | value = azurerm_kubernetes_cluster.aks.kube_config.0.host 13 | sensitive = true 14 | } 15 | 16 | output "client_certificate" { 17 | value = azurerm_kubernetes_cluster.aks.kube_config.0.client_certificate 18 | sensitive = true 19 | } 20 | 21 | output "client_key" { 22 | value = azurerm_kubernetes_cluster.aks.kube_config.0.client_key 23 | sensitive = true 24 | } 25 | 26 | output "cluster_ca_certificate" { 27 | value = azurerm_kubernetes_cluster.aks.kube_config.0.cluster_ca_certificate 28 | sensitive = true 29 | } 30 | -------------------------------------------------------------------------------- /test/multicloud/modules/aks/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "1.8.3" 3 | required_providers { 4 | azurerm = { 5 | source = "hashicorp/azurerm" 6 | version = "4.15.0" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/multicloud/modules/eks/outputs.tf: -------------------------------------------------------------------------------- 1 | output "aws_get_kubeconfig" { 2 | value = "aws eks update-kubeconfig --name ${aws_eks_cluster.eks.name} --region ${var.region}" 3 | description = "Run this command to fetch the kubeconfig for your EKS cluster" 4 | } 5 | 6 | output "cluster_name" { 7 | value = aws_eks_cluster.eks.name 8 | description = "EKS cluster name" 9 | } 10 | 11 | output "access_token" { 12 | value = data.aws_eks_cluster_auth.eks.token 13 | sensitive = true 14 | } 15 | 16 | output "host" { 17 | value = data.aws_eks_cluster.eks.endpoint 18 | sensitive = true 19 | } 20 | 21 | output "cluster_ca_certificate" { 22 | value = data.aws_eks_cluster.eks.certificate_authority[0].data 23 | sensitive = true 24 | } 25 | -------------------------------------------------------------------------------- /test/multicloud/modules/eks/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | source = "hashicorp/aws" 5 | version = "5.88.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/multicloud/modules/eks/variables.tf: -------------------------------------------------------------------------------- 1 | variable "prefix" { 2 | description = "A prefix to add to all resources." 3 | type = string 4 | } 5 | 6 | variable "region" { 7 | description = "The AWS region to deploy to." 8 | type = string 9 | } -------------------------------------------------------------------------------- /test/multicloud/modules/gke/output.tf: -------------------------------------------------------------------------------- 1 | output "gcloud_get_kubeconfig" { 2 | value = "gcloud container clusters get-credentials ${google_container_cluster.gke.name} --region ${google_container_cluster.gke.location} --project ${google_container_cluster.gke.project}" 3 | description = "Run this command to fetch the kubeconfig for your GKE cluster" 4 | } 5 | 6 | output "cluster_name" { 7 | value = google_container_cluster.gke.name 8 | description = "GKE cluster name" 9 | } 10 | 11 | output "host" { 12 | value = "https://${google_container_cluster.gke.endpoint}" 13 | sensitive = true 14 | } 15 | 16 | output "cluster_ca_certificate" { 17 | value = google_container_cluster.gke.master_auth.0.cluster_ca_certificate 18 | sensitive = true 19 | } -------------------------------------------------------------------------------- /test/multicloud/modules/gke/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "1.8.3" 3 | required_providers { 4 | google = { 5 | source = "hashicorp/google" 6 | version = "6.17.0" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /test/multicloud/modules/gke/variables.tf: -------------------------------------------------------------------------------- 1 | variable "prefix" { 2 | description = "Prefix for resource names" 3 | type = string 4 | } 5 | 6 | variable "project" { 7 | description = "Project ID" 8 | type = string 9 | } 10 | 11 | variable "location" { 12 | description = "Region for the GKE cluster and subnet" 13 | type = string 14 | } 15 | 16 | variable "machine_type" { 17 | description = "Machine type for the GKE node pool" 18 | type = string 19 | } 20 | 21 | variable "subnet_cidr" { 22 | description = "CIDR range for the subnet" 23 | type = string 24 | default = "10.0.0.0/24" 25 | } 26 | -------------------------------------------------------------------------------- /test/multicloud/modules/grafana-pdc-agent/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | kubernetes = { 4 | source = "hashicorp/kubernetes" 5 | version = "2.35.1" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /test/multicloud/modules/grafana-pdc-agent/variables.tf: -------------------------------------------------------------------------------- 1 | variable "grafana_pdc_token" { 2 | description = "The token for the Grafana PDC agent." 3 | type = string 4 | sensitive = true 5 | } 6 | 7 | variable "grafana_pdc_hosted_grafana_id" { 8 | description = "The hosted Grafana ID for the Grafana PDC agent." 9 | type = string 10 | } 11 | 12 | variable "grafana_pdc_cluster" { 13 | description = "The cluster name for the Grafana PDC agent." 14 | type = string 15 | } -------------------------------------------------------------------------------- /test/multicloud/modules/grafana/outputs.tf: -------------------------------------------------------------------------------- 1 | output "pdc_network_token" { 2 | value = grafana_cloud_private_data_source_connect_network_token.pdc_network_token.token 3 | sensitive = true 4 | } -------------------------------------------------------------------------------- /test/multicloud/modules/grafana/providers.tf: -------------------------------------------------------------------------------- 1 | # Terraform Grafana provider configuration 2 | terraform { 3 | required_version = "1.8.3" 4 | required_providers { 5 | grafana = { 6 | source = "grafana/grafana" 7 | version = "3.18.3" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/multicloud/modules/grafana/variables.tf: -------------------------------------------------------------------------------- 1 | variable "dashboards" { 2 | description = "A map of dashboards to add." 3 | type = map(string) 4 | default = {} 5 | } 6 | 7 | variable "cluster_reference" { 8 | description = "The cluster reference to use for the Grafana data source." 9 | type = string 10 | } 11 | 12 | variable "hosted_grafana_id" { 13 | description = "The hosted Grafana ID for the Grafana PDC agent." 14 | type = string 15 | } 16 | 17 | variable "grafana_region" { 18 | description = "The region for the Grafana instance." 19 | type = string 20 | } 21 | -------------------------------------------------------------------------------- /test/multicloud/modules/helm-release/main.tf: -------------------------------------------------------------------------------- 1 | resource "helm_release" "release" { 2 | name = var.release_name 3 | namespace = var.release_namespace 4 | repository = var.repository_url 5 | chart = var.chart_name 6 | version = var.chart_version 7 | recreate_pods = true 8 | values = [jsonencode(var.values)] 9 | 10 | dynamic "set" { 11 | for_each = var.custom_values 12 | content { 13 | name = set.key 14 | value = set.value 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /test/multicloud/modules/helm-release/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | helm = { 4 | source = "hashicorp/helm" 5 | version = "2.17.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/multicloud/modules/helm-release/variables.tf: -------------------------------------------------------------------------------- 1 | variable "release_name" { 2 | description = "The name of the Helm release." 3 | type = string 4 | } 5 | 6 | variable "release_namespace" { 7 | description = "The namespace to install the Helm chart." 8 | type = string 9 | default = "default" 10 | } 11 | 12 | variable "repository_url" { 13 | description = "The URL of the Helm repository." 14 | type = string 15 | } 16 | 17 | variable "chart_version" { 18 | description = "The version of the Helm chart to install." 19 | type = string 20 | } 21 | 22 | variable "chart_name" { 23 | description = "The name of the Helm chart to install." 24 | type = string 25 | } 26 | 27 | variable "values" { 28 | description = "This corresponds to Helm values.yaml" 29 | type = any 30 | } 31 | 32 | variable "custom_values" { 33 | description = "The name of the cluster." 34 | type = map(any) 35 | default = {} 36 | } 37 | -------------------------------------------------------------------------------- /test/multicloud/modules/kind/main.tf: -------------------------------------------------------------------------------- 1 | resource "kind_cluster" "kind" { 2 | name = "${var.prefix}-kind" 3 | wait_for_ready = true 4 | kind_config { 5 | kind = "Cluster" 6 | api_version = "kind.x-k8s.io/v1alpha4" 7 | 8 | node { 9 | role = "control-plane" 10 | } 11 | 12 | node { 13 | role = "worker" 14 | } 15 | 16 | node { 17 | role = "worker" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /test/multicloud/modules/kind/output.tf: -------------------------------------------------------------------------------- 1 | output "kubeconfig" { 2 | value = kind_cluster.kind.kubeconfig 3 | sensitive = true 4 | } 5 | 6 | output "cluster_name" { 7 | value = kind_cluster.kind.name 8 | } 9 | 10 | output "host" { 11 | value = kind_cluster.kind.endpoint 12 | sensitive = true 13 | } 14 | 15 | output "client_certificate" { 16 | value = kind_cluster.kind.client_certificate 17 | sensitive = true 18 | } 19 | 20 | output "client_key" { 21 | value = kind_cluster.kind.client_key 22 | sensitive = true 23 | } 24 | 25 | output "cluster_ca_certificate" { 26 | value = kind_cluster.kind.cluster_ca_certificate 27 | sensitive = true 28 | } -------------------------------------------------------------------------------- /test/multicloud/modules/kind/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "1.8.3" 3 | required_providers { 4 | kind = { 5 | source = "tehcyx/kind" 6 | version = "0.7.0" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /test/multicloud/modules/kind/variables.tf: -------------------------------------------------------------------------------- 1 | variable "prefix" { 2 | description = "A prefix to add to all resources." 3 | type = string 4 | } -------------------------------------------------------------------------------- /test/multicloud/test/utils/types.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | const ( 4 | ExamplesPath = "../../examples/" 5 | RetinaVersion = "v0.0.24" 6 | PrometheusHelmValuesStandard = "../../../../deploy/standard/prometheus/values.yaml" 7 | ) 8 | 9 | type PodSelector struct { 10 | Namespace string 11 | LabelSelector string 12 | ContainerName string 13 | } 14 | -------------------------------------------------------------------------------- /test/profiles/advanced/crd/metrics_config_crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: retina.sh/v1alpha1 2 | kind: MetricsConfiguration 3 | metadata: 4 | name: metricsconfigcrd 5 | spec: 6 | contextOptions: 7 | - metricName: drop_count 8 | sourceLabels: 9 | - ip 10 | - pod 11 | - port 12 | additionalLabels: 13 | - direction 14 | - metricName: forward_count 15 | sourceLabels: 16 | - ip 17 | - pod 18 | - port 19 | additionalLabels: 20 | - direction 21 | namespaces: 22 | exclude: 23 | - kube-system 24 | -------------------------------------------------------------------------------- /test/profiles/advanced/values.yaml: -------------------------------------------------------------------------------- 1 | enablePodLevel: true 2 | enableAnnotations: true 3 | operator: 4 | enabled: true 5 | enableRetinaEndpoint: true 6 | -------------------------------------------------------------------------------- /test/profiles/basic/crd/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/test/profiles/basic/crd/.gitkeep -------------------------------------------------------------------------------- /test/profiles/basic/values.yaml: -------------------------------------------------------------------------------- 1 | enablePodLevel: false 2 | operator: 3 | enabled: false 4 | # Plugins 5 | -------------------------------------------------------------------------------- /test/profiles/localctx/crd/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/retina/59014f78ed3d916f720d13778e0a7f3d5866f705/test/profiles/localctx/crd/.gitkeep -------------------------------------------------------------------------------- /test/profiles/localctx/values.yaml: -------------------------------------------------------------------------------- 1 | operator: 2 | enabled: false 3 | # Plugins will default to deploy/standard/manifests/controller/helm/retina/values.yaml 4 | # TODO add all plugins that we want to test here for local context. 5 | remoteContext: false 6 | enablePodLevel: true 7 | enableAnnotations: true 8 | enabledPlugin_linux: '["dropreason","packetforward","packetparser", "dns"]' 9 | -------------------------------------------------------------------------------- /test/prometheus/ama-metrics/prometheus-config: -------------------------------------------------------------------------------- 1 | kind: ConfigMap 2 | apiVersion: v1 3 | data: 4 | pod-annotation-based-scraping: |- 5 | podannotationnamespaceregex = "" 6 | metadata: 7 | name: ama-metrics-settings-configmap 8 | namespace: kube-system 9 | -------------------------------------------------------------------------------- /test/prometheus/create-cm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | kubectl apply -f ./test/prometheus/service.yaml 3 | 4 | kubectl delete configmap ama-metrics-prometheus-config-node -n kube-system 5 | #kubectl create configmap ama-metrics-prometheus-config-node --from-file=./test/prometheus/ama-metrics-node/prometheus-config -n kube-system 6 | 7 | kubectl delete configmap ama-metrics-prometheus-config -n kube-system 8 | # kubectl create configmap ama-metrics-prometheus-config --from-file=./test/prometheus/ama-metrics/prometheus-config -n kube-system 9 | kubectl apply -f ./test/prometheus/ama-metrics/prometheus-config -n kube-system 10 | 11 | kubectl rollout restart ds ama-metrics-node -n kube-system 12 | kubectl rollout restart deploy ama-metrics -n kube-system 13 | -------------------------------------------------------------------------------- /test/prometheus/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: networkobservability-test 5 | spec: 6 | ports: 7 | - name: retina 8 | protocol: TCP 9 | port: 10093 10 | targetPort: 10093 11 | -------------------------------------------------------------------------------- /test/retry/retry.go: -------------------------------------------------------------------------------- 1 | // todo: there are more robust retry packages out there, discuss with team 2 | package retry 3 | 4 | import ( 5 | "context" 6 | "fmt" 7 | "time" 8 | ) 9 | 10 | // a Retrier can attempt an operation multiple times, based on some thresholds 11 | type Retrier struct { 12 | Attempts int 13 | Delay time.Duration 14 | ExpBackoff bool 15 | } 16 | 17 | func (r Retrier) Do(ctx context.Context, f func() error) error { 18 | done := make(chan struct{}) 19 | var err error 20 | go func() { 21 | defer func() { done <- struct{}{} }() 22 | for i := 0; i < r.Attempts; i++ { 23 | err = f() 24 | if err == nil { 25 | break 26 | } 27 | time.Sleep(r.Delay) 28 | if r.ExpBackoff { 29 | r.Delay *= 2 30 | } 31 | } 32 | }() 33 | 34 | select { 35 | case <-ctx.Done(): 36 | ctxErr := ctx.Err() 37 | if ctxErr != nil { 38 | return fmt.Errorf("context error: %w", ctxErr) 39 | } 40 | return nil 41 | case <-done: 42 | return err 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /test/scale/README.md: -------------------------------------------------------------------------------- 1 | # Retina Scale Testing 2 | 3 | * example-*.yaml files are used to generate resources for the cluster using `./generate-yamls.sh`. This generates cluster role bindings, deployments, network polcies, and service accounts. 4 | 5 | * `create-all.sh` will create all the resources for the cluster. 6 | 7 | * `cpu-and-mem.sh` is the script used to track the cpu and mem of retina pods, and node metrics and output the results as a csv in `./results/`. 8 | 9 | * `pprof.sh` will get the pprof for retina agents which have mem > 100 Mb and will output the results in `./results/$pod`. 10 | 11 | * `restarts.sh` will get the previous logs for retina agents which have restarted and will output the results in `./results`. 12 | 13 | * `scrape-metrics.sh` is currently not used, but can be used/modified to go through each retina pod and get logs or metrics. 14 | 15 | * `az aks nodepool scale --name --cluster-name --resource-group --node-count 1000` was used to scale to 1k nodes for testing. 16 | -------------------------------------------------------------------------------- /test/scale/create-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ./create-ns.sh 3 | ./create-sa.sh 4 | ./create-crb.sh 5 | ./create-netpols.sh 6 | ./create-deployments.sh 7 | -------------------------------------------------------------------------------- /test/scale/create-crb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | numNamespaces=`kubectl get ns | grep test-ns- | wc -l` 4 | numClusterrolebindings=`ls clusterrolebindings/ | wc -l` 5 | startTime=`date -u` 6 | 7 | echo "creating $numClusterrolebindings clusterrolebindings" 8 | for (( i=1; i<=$numNamespaces; i++ )); do 9 | kubectl -n test-ns-$i apply -f clusterrolebindings/ 10 | done 11 | 12 | endTime=`date -u` 13 | echo 14 | echo "DONE. All $numClusterrolebindings clusterrolebindings are created" 15 | elapsedTime=$(( $(date -d "$endTime" '+%s') - $(date -d "$startTime" '+%s') )) 16 | echo "Elapsed time: $(( elapsedTime / 60 )) minutes $(( elapsedTime % 60 )) seconds" 17 | echo "start time: $startTime" 18 | echo "end time: $endTime" 19 | -------------------------------------------------------------------------------- /test/scale/create-netpols.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | numNamespaces=`kubectl get ns | grep test-ns- | wc -l` 4 | numPolicies=`ls netpols/ | wc -l` 5 | totalNetPols=$(( numPolicies * numNamespaces )) 6 | startTime=`date -u` 7 | 8 | echo "creating $totalNetPols network policies, $numPolicies in each of $numNamespaces namespaces" 9 | for (( i=1; i<=$numNamespaces; i++ )); do 10 | kubectl -n test-ns-$i apply -f netpols/ 11 | done 12 | 13 | endTime=`date -u` 14 | echo 15 | echo "DONE. All $totalNetPols policies are created" 16 | elapsedTime=$(( $(date -d "$endTime" '+%s') - $(date -d "$startTime" '+%s') )) 17 | echo "Elapsed time: $(( elapsedTime / 60 )) minutes $(( elapsedTime % 60 )) seconds" 18 | echo "start time: $startTime" 19 | echo "end time: $endTime" 20 | -------------------------------------------------------------------------------- /test/scale/create-ns.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | numNamespaces=1 3 | 4 | set -e 5 | 6 | startTime=`date -u` 7 | summary="creating $numNamespaces namespaces" 8 | echo "$summary" 9 | for (( i=1; i<=$numNamespaces; i++ )); do 10 | kubectl create namespace test-ns-$i 11 | done 12 | -------------------------------------------------------------------------------- /test/scale/create-sa.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | numNamespaces=`kubectl get ns | grep test-ns- | wc -l` 4 | numServiceAccounts=`ls serviceaccounts/ | wc -l` 5 | startTime=`date -u` 6 | 7 | echo "creating $numServiceAccounts service accounts" 8 | kubectl apply -f serviceaccounts/ 9 | 10 | endTime=`date -u` 11 | echo 12 | echo "DONE. All $numServiceAccounts service accounts are created" 13 | elapsedTime=$(( $(date -d "$endTime" '+%s') - $(date -d "$startTime" '+%s') )) 14 | echo "Elapsed time: $(( elapsedTime / 60 )) minutes $(( elapsedTime % 60 )) seconds" 15 | echo "start time: $startTime" 16 | echo "end time: $endTime" 17 | -------------------------------------------------------------------------------- /test/scale/example-clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | name: default 6 | roleRef: 7 | apiGroup: rbac.authorization.k8s.io 8 | kind: ClusterRole 9 | name: view 10 | subjects: 11 | - kind: ServiceAccount 12 | name: goldpinger-serviceaccount 13 | namespace: labelReplaceNamespace 14 | -------------------------------------------------------------------------------- /test/scale/example-netpol.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: NetworkPolicy 3 | metadata: 4 | name: nameReplace 5 | spec: 6 | podSelector: 7 | matchLabels: 8 | app: labelReplace1 9 | policyTypes: 10 | - Ingress 11 | - Egress 12 | ingress: 13 | - from: 14 | - podSelector: 15 | matchLabels: 16 | app: labelReplace2 17 | ports: 18 | - protocol: TCP 19 | port: 8080 20 | egress: 21 | - to: 22 | - podSelector: 23 | matchLabels: 24 | app: labelReplace3 25 | ports: 26 | - protocol: TCP 27 | port: 8080 28 | -------------------------------------------------------------------------------- /test/scale/example-serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: goldpinger-serviceaccount 6 | namespace: labelReplaceNamespace 7 | -------------------------------------------------------------------------------- /test/scale/restarts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Script to get the previous logs of pods that have restarted on the cluster 4 | 5 | echo "pod,restarts,error" > pod-restarts.out 6 | lines=`kubectl get pod -n kube-system | awk '{$1=$1;print}' | grep retina | tr ' ' ','` 7 | for line in $lines; do 8 | IFS=',' 9 | read -ra values <<< "$line" 10 | pod="${values[0]}" 11 | restarts="${values[3]}" 12 | echo "Getting previous logs for $pod with $restarts restarts" 13 | if [ $restarts -gt 0 ]; then 14 | err=`kubectl logs -n kube-system $pod --previous` 15 | echo "$pod,$restarts,$err" >> ./results/pod-restarts.out 16 | fi 17 | IFS=' ' 18 | done 19 | -------------------------------------------------------------------------------- /test/testcrds/metrics-config-goldpinger.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: retina.sh/v1alpha1 2 | kind: MetricsConfiguration 3 | metadata: 4 | name: metricsconfigurationaaaaa 5 | spec: 6 | namespaces: 7 | include: 8 | - default 9 | contextOptions: 10 | - metricName: forward_count 11 | sourceLabels: 12 | - podName 13 | - ip 14 | destinationLabels: 15 | - podName 16 | - ip 17 | - workload 18 | - metricName: drop_count 19 | sourceLabels: 20 | - podName 21 | - ip 22 | destinationLabels: 23 | - podName 24 | - ip 25 | - workload 26 | - metricName: tcp_retransmission_count 27 | sourceLabels: 28 | - podName 29 | - ip 30 | destinationLabels: 31 | - podName 32 | - ip 33 | - workload 34 | -------------------------------------------------------------------------------- /test/trafficgen/deny.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: networking.k8s.io/v1 3 | kind: NetworkPolicy 4 | metadata: 5 | name: default-deny-ingress 6 | namespace: default 7 | spec: 8 | podSelector: 9 | matchLabels: 10 | # agnhost: b 11 | server: bad 12 | policyTypes: 13 | - Ingress 14 | -------------------------------------------------------------------------------- /test/watchers/veth/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment 5 | namespace: default 6 | labels: 7 | app: nginx 8 | spec: 9 | replicas: 0 10 | selector: 11 | matchLabels: 12 | app: nginx 13 | template: 14 | metadata: 15 | labels: 16 | app: nginx 17 | spec: 18 | containers: 19 | - name: nginx 20 | # image: nginx:1.14.2 21 | image: mcr.microsoft.com/mirror/docker/library/nginx:1.23 22 | ports: 23 | - containerPort: 80 24 | nodeSelector: 25 | # kubernetes.io/hostname: aks-nodepool1-29238948-vmss000000 26 | # kubernetes.io/hostname: aks-arm64-36093013-vmss000000 27 | -------------------------------------------------------------------------------- /test/watchers/veth/main.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | // nolint 4 | 5 | package main 6 | 7 | import ( 8 | "context" 9 | "time" 10 | 11 | "github.com/microsoft/retina/pkg/log" 12 | "github.com/microsoft/retina/pkg/managers/watchermanager" 13 | "github.com/microsoft/retina/pkg/watchers/endpoint" 14 | "go.uber.org/zap" 15 | ) 16 | 17 | func main() { 18 | opts := log.GetDefaultLogOpts() 19 | opts.Level = "debug" 20 | log.SetupZapLogger(opts) 21 | l := log.Logger().Named("test-veth") 22 | 23 | ctx := context.Background() 24 | 25 | // watcher manager 26 | wm := watchermanager.NewWatcherManager() 27 | wm.Watchers = []watchermanager.IWatcher{endpoint.Watcher()} 28 | 29 | err := wm.Start(ctx) 30 | if err != nil { 31 | panic(err) 32 | } 33 | 34 | // Sleep 1 minute. 35 | time.Sleep(60 * time.Second) 36 | 37 | err = wm.Stop(ctx) 38 | if err != nil { 39 | l.Error("Failed to start watcher manager", zap.Error(err)) 40 | panic(err) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /windows/docker/DockerBuild.ps1: -------------------------------------------------------------------------------- 1 | # Import the DockerBuildModule 2 | #Import-Module -Name .\DockerBuildModule.psm1 3 | $ErrorActionPreference = "Stop" 4 | 5 | Build-RetinaBuilderImage -version "v2" 6 | 7 | # Get the version for the Retina builder image 8 | $builderVersion = Get-GitVersion 9 | 10 | # Define the builder image version you want to use 11 | #$customBuilderImageVersion = "custom-version" 12 | 13 | # Define the full custom builder image name with the custom version 14 | $customBuilderImageName = "$defaultRegistry/retina-builder:$customBuilderImageVersion" 15 | 16 | # Call the Build-RetinaAgentImage function with the custom builder image name 17 | Build-RetinaAgentImage 18 | -------------------------------------------------------------------------------- /windows/docker/notes.md: -------------------------------------------------------------------------------- 1 | # Used for CI, but also useful locally 2 | -------------------------------------------------------------------------------- /windows/kubeconfigtemplate.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Config 3 | clusters: 4 | - name: kubernetes 5 | cluster: 6 | certificate-authority-data: 7 | 8 | contexts: 9 | - name: azure-retina-windows@kubernetes 10 | context: 11 | cluster: kubernetes 12 | namespace: kube-system 13 | user: azure-retina-windows 14 | current-context: azure-retina-windows@kubernetes 15 | users: 16 | - name: azure-retina-windows 17 | user: 18 | token: 19 | -------------------------------------------------------------------------------- /windows/manifests/node-selector-patch.yaml: -------------------------------------------------------------------------------- 1 | spec: 2 | template: 3 | spec: 4 | nodeSelector: 5 | kubernetes.io/os: linux 6 | --------------------------------------------------------------------------------