diff --git a/Makefile b/Makefile index 67e17640..824cf965 100644 --- a/Makefile +++ b/Makefile @@ -174,7 +174,7 @@ check-help: ## Cursory check of the help menus ## : ## _ [E2E tests suite] e2e-build: set-forwarding ## E2E. Build dockers and containers for e2e-tests - ./docker/docker_build.sh e2e ${BUILD_OPTS_DEPLOY} + ./docker/docker_build.sh e2e ${BUILD_OPTS_DEPLOY} $(BUILD_ARCH) e2e-run: ## E2E. Start e2e environment bash -c "DOCKER_TAG=e2e docker compose up -d" @@ -231,7 +231,7 @@ reset-forwarding: ## : ## _ [Interactive integration tests] integration-env-build: set-forwarding #build - ./docker/docker_build.sh integration ${BUILD_OPTS_DEPLOY} + ./docker/docker_build.sh integration ${BUILD_OPTS_DEPLOY} $(BUILD_ARCH) bash -c "DOCKER_TAG=integration docker compose up -d" integration-env-start: set-forwarding #start diff --git a/cmd/dmsg-monitor/README.md b/cmd/dmsg-monitor/README.md new file mode 100644 index 00000000..56f5af2a --- /dev/null +++ b/cmd/dmsg-monitor/README.md @@ -0,0 +1,16 @@ +# DMSG Monitor + +## API endpoints + +### GET `/health` +Gets the health info of the service. e.g. +``` +{ + "build_info": { + "version": "v1.0.1-267-ge1617c5b", + "commit": "e1617c5b0121182cfd2b610dc518e4753e56440e", + "date": "2022-10-25T11:01:52Z" + }, + "started_at": "2022-10-25T11:10:45.152629597Z" +} +``` \ No newline at end of file diff --git a/cmd/dmsg-monitor/commands/root.go b/cmd/dmsg-monitor/commands/root.go new file mode 100644 index 00000000..ec48499e --- /dev/null +++ b/cmd/dmsg-monitor/commands/root.go @@ -0,0 +1,123 @@ +// Package commands cmd/dmsg-monitor/commands/root.go +package commands + +import ( + "context" + "fmt" + "log" + "os" + "path/filepath" + "strings" + "time" + + "github.com/skycoin/skywire-utilities/pkg/buildinfo" + "github.com/skycoin/skywire-utilities/pkg/cipher" + "github.com/skycoin/skywire-utilities/pkg/cmdutil" + "github.com/skycoin/skywire-utilities/pkg/logging" + "github.com/skycoin/skywire-utilities/pkg/tcpproxy" + "github.com/spf13/cobra" + + "github.com/skycoin/skywire-services/pkg/dmsg-monitor/api" +) + +var ( + confPath string + dmsgURL string + utURL string + addr string + tag string + logLvl string + sleepDeregistration time.Duration + batchSize int +) + +func init() { + RootCmd.Flags().StringVarP(&addr, "addr", "a", ":9080", "address to bind to.\033[0m") + RootCmd.Flags().DurationVarP(&sleepDeregistration, "sleep-deregistration", "s", 60, "Sleep time for derigstration process in minutes\033[0m") + RootCmd.Flags().IntVarP(&batchSize, "batchsize", "b", 20, "Batch size of deregistration\033[0m") + RootCmd.Flags().StringVarP(&confPath, "config", "c", "dmsg-monitor.json", "config file location.\033[0m") + RootCmd.Flags().StringVarP(&dmsgURL, "dmsg-url", "d", "", "url to dmsg data.\033[0m") + RootCmd.Flags().StringVarP(&utURL, "ut-url", "u", "", "url to uptime tracker visor data.\033[0m") + RootCmd.Flags().StringVar(&tag, "tag", "dmsg_monitor", "logging tag\033[0m") + RootCmd.Flags().StringVarP(&logLvl, "loglvl", "l", "info", "set log level one of: info, error, warn, debug, trace, panic") +} + +// RootCmd contains the root command +var RootCmd = &cobra.Command{ + Use: func() string { + return strings.Split(filepath.Base(strings.ReplaceAll(strings.ReplaceAll(fmt.Sprintf("%v", os.Args), "[", ""), "]", "")), " ")[0] + }(), + Short: "DMSG monitor of DMSG discovery entries.", + Long: ` + ┌┬┐┌┬┐┌─┐┌─┐ ┌┬┐┌─┐┌┐┌┬┌┬┐┌─┐┬─┐ + │││││└─┐│ ┬───││││ │││││ │ │ │├┬┘ + ─┴┘┴ ┴└─┘└─┘ ┴ ┴└─┘┘└┘┴ ┴ └─┘┴└─ +`, + SilenceErrors: true, + SilenceUsage: true, + DisableSuggestions: true, + DisableFlagsInUseLine: true, + Version: buildinfo.Version(), + Run: func(_ *cobra.Command, _ []string) { + if _, err := buildinfo.Get().WriteTo(os.Stdout); err != nil { + log.Printf("Failed to output build info: %v", err) + } + + mLogger := logging.NewMasterLogger() + lvl, err := logging.LevelFromString(logLvl) + if err != nil { + mLogger.Fatal("Invalid log level") + } + logging.SetLevel(lvl) + + conf := api.InitConfig(confPath, mLogger) + + if dmsgURL == "" { + dmsgURL = conf.Dmsg.Discovery + } + if utURL == "" { + utURL = conf.UptimeTracker.Addr + "/uptimes" + } + + var srvURLs api.ServicesURLs + srvURLs.DMSG = dmsgURL + srvURLs.UT = utURL + + logger := mLogger.PackageLogger(tag) + + logger.WithField("addr", addr).Info("Serving DMSG-Monitor API...") + + monitorSign, _ := cipher.SignPayload([]byte(conf.PK.Hex()), conf.SK) //nolint + + var monitorConfig api.DMSGMonitorConfig + monitorConfig.PK = conf.PK + monitorConfig.Sign = monitorSign + monitorConfig.BatchSize = batchSize + + dmsgMonitorAPI := api.New(logger, srvURLs, monitorConfig) + + ctx, cancel := cmdutil.SignalContext(context.Background(), logger) + defer cancel() + + go dmsgMonitorAPI.InitDeregistrationLoop(ctx, conf, sleepDeregistration) + + go func() { + if err := tcpproxy.ListenAndServe(addr, dmsgMonitorAPI); err != nil { + logger.Errorf("serve: %v", err) + cancel() + } + }() + + <-ctx.Done() + if err := dmsgMonitorAPI.Visor.Close(); err != nil { + logger.WithError(err).Error("Visor closed with error.") + } + }, +} + +// Execute executes root CLI command. +func Execute() { + if err := RootCmd.Execute(); err != nil { + log.Fatal("Failed to execute command: ", err) + } +} diff --git a/cmd/dmsg-monitor/dmsg-monitor.go b/cmd/dmsg-monitor/dmsg-monitor.go new file mode 100644 index 00000000..9a4b1224 --- /dev/null +++ b/cmd/dmsg-monitor/dmsg-monitor.go @@ -0,0 +1,43 @@ +// Package main cmd/dmsg-monitor/dmsg-monitor.go +package main + +import ( + cc "github.com/ivanpirog/coloredcobra" + "github.com/spf13/cobra" + + "github.com/skycoin/skywire-services/cmd/dmsg-monitor/commands" +) + +func init() { + var helpflag bool + commands.RootCmd.SetUsageTemplate(help) + commands.RootCmd.PersistentFlags().BoolVarP(&helpflag, "help", "h", false, "help for dmsgpty-cli") + commands.RootCmd.SetHelpCommand(&cobra.Command{Hidden: true}) + commands.RootCmd.PersistentFlags().MarkHidden("help") //nolint +} + +func main() { + cc.Init(&cc.Config{ + RootCmd: commands.RootCmd, + Headings: cc.HiBlue + cc.Bold, + Commands: cc.HiBlue + cc.Bold, + CmdShortDescr: cc.HiBlue, + Example: cc.HiBlue + cc.Italic, + ExecName: cc.HiBlue + cc.Bold, + Flags: cc.HiBlue + cc.Bold, + FlagsDescr: cc.HiBlue, + NoExtraNewlines: true, + NoBottomNewline: true, + }) + commands.Execute() +} + +const help = "Usage:\r\n" + + " {{.UseLine}}{{if .HasAvailableSubCommands}}{{end}} {{if gt (len .Aliases) 0}}\r\n\r\n" + + "{{.NameAndAliases}}{{end}}{{if .HasAvailableSubCommands}}\r\n\r\n" + + "Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand)}}\r\n " + + "{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}\r\n\r\n" + + "Flags:\r\n" + + "{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}\r\n\r\n" + + "Global Flags:\r\n" + + "{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}\r\n\r\n" \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index cf85559c..ff00e7bb 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,5 +1,3 @@ -version: "3.7" - networks: srv: driver: "bridge" diff --git a/docker/docker_build.sh b/docker/docker_build.sh index a96f20d3..185dbd6f 100755 --- a/docker/docker_build.sh +++ b/docker/docker_build.sh @@ -4,6 +4,7 @@ trap "exit" INT ## Variables image_tag="$1" go_buildopts="$2" +build_arch="$3" git_branch="$(git rev-parse --abbrev-ref HEAD)" nv_dev_url="https://nv.skywire.dev/map" nv_prod_url="https://nv.skycoin.com/map" @@ -15,7 +16,7 @@ platform="--platform=linux/amd64" registry="$REGISTRY" # shellcheck disable=SC2153 -base_image=golang:1.21-alpine +base_image=golang:1.23-alpine if [[ "$#" != 2 ]]; then echo "docker_build.sh " @@ -25,6 +26,10 @@ if [[ "$go_buildopts" == "" ]]; then go_buildopts="-mod=vendor -ldflags\"-w -s\"" fi +if [[ "$build_arch" != "" ]]; then + platform="--platform=$build_arch" +fi + if [[ "$git_branch" != "master" ]] && [[ "$git_branch" != "develop" ]]; then git_branch="develop" fi @@ -64,6 +69,7 @@ if [[ "$image_tag" == "e2e" ]]; then DOCKER_BUILDKIT="$bldkit" docker build -f docker/images/dmsg-discovery/Dockerfile \ --build-arg build_opts="$go_buildopts" \ --build-arg image_tag="$image_tag" \ + $platform \ --build-arg base_image="skycoin/dmsg-discovery:$dockerhub_image_tag" \ -t "$registry"/dmsg-discovery:"$image_tag" . @@ -72,6 +78,7 @@ if [[ "$image_tag" == "e2e" ]]; then --build-arg base_image="skycoin/dmsg-server:$dockerhub_image_tag" \ --build-arg build_opts="$go_buildopts" \ --build-arg image_tag="$image_tag" \ + $platform \ -t "$registry"/dmsg-server:"$image_tag" . echo "build service discovery image" @@ -81,13 +88,6 @@ if [[ "$image_tag" == "e2e" ]]; then --build-arg image_tag="$image_tag" \ $platform \ -t "$registry"/service-discovery:"$image_tag" . - - echo "building uptime tracker image" - DOCKER_BUILDKIT="$bldkit" docker build -f docker/images/uptime-tracker/Dockerfile \ - --build-arg base_image="$base_image" \ - --build-arg build_opts="$go_buildopts" \ - --build-arg image_tag="$image_tag" \ - -t "$registry"/uptime-tracker:"$image_tag" . rm -rf ./tmp/skycoin-service-discovery fi @@ -97,26 +97,27 @@ if [[ "$image_tag" == "integration" ]]; then rm -rf ./tmp/skycoin-service-discovery rm -rf ./tmp/dmsg rm -rf ./tmp/skywire - rm -rf ./tmp/skywire-ut cp -r ../skycoin-service-discovery ./tmp cp -r ../dmsg ./tmp cp -r ../skywire ./tmp - cp -r ../skywire-ut ./tmp echo ==================================================== echo "BUILDING SKYWIRE VISOR" DOCKER_BUILDKIT="$bldkit" docker build -f docker/images/skywire-visor/DockerfileInt \ + $platform \ -t "$registry"/skywire-visor:"$image_tag" . echo ============ Base images ready ====================== echo "build dmsg discovery image" DOCKER_BUILDKIT="$bldkit" docker build -f docker/images/dmsg-discovery/DockerfileInt \ + $platform \ -t "$registry"/dmsg-discovery:"$image_tag" . echo "build dmsg server image" DOCKER_BUILDKIT="$bldkit" docker build -f docker/images/dmsg-server/DockerfileInt \ + $platform \ -t "$registry"/dmsg-server:"$image_tag" . echo "build service discovery image" @@ -124,14 +125,8 @@ if [[ "$image_tag" == "integration" ]]; then --build-arg base_image="$base_image" \ --build-arg build_opts="$go_buildopts" \ --build-arg image_tag="$image_tag" \ + $platform \ -t "$registry"/service-discovery:"$image_tag" . - - echo "building uptime tracker image" - DOCKER_BUILDKIT="$bldkit" docker build -f docker/images/uptime-tracker/Dockerfile \ - --build-arg base_image="$base_image" \ - --build-arg build_opts="$go_buildopts" \ - --build-arg image_tag="$image_tag" \ - -t "$registry"/uptime-tracker:"$image_tag" . rm -rf ./tmp/* fi @@ -205,14 +200,6 @@ DOCKER_BUILDKIT="$bldkit" docker build -f docker/images/network-monitor/Dockerfi $platform \ -t "$registry"/network-monitor:"$image_tag" . -echo "building liveness checker image" -DOCKER_BUILDKIT="$bldkit" docker build -f docker/images/liveness-checker/Dockerfile \ - --build-arg base_image="$base_image" \ - --build-arg build_opts="$go_buildopts" \ - --build-arg image_tag="$image_tag" \ - $platform \ - -t "$registry"/liveness-checker:"$image_tag" . - echo "building config bootstrapper image" DOCKER_BUILDKIT="$bldkit" docker build -f docker/images/config-bootstrapper/Dockerfile \ --build-arg base_image="$base_image" \ diff --git a/docker/docker_clean.sh b/docker/docker_clean.sh index 931bda42..2ce5e832 100755 --- a/docker/docker_clean.sh +++ b/docker/docker_clean.sh @@ -19,7 +19,6 @@ declare -a images_arr=( "skycoin/network-monitor:${image_tag}" # "skycoin/node-visualizer:${image_tag}" "skycoin/config-bootstrapper:${image_tag}" - "skycoin/liveness-checker:${image_tag}" "skycoin/vpn-monitor:${image_tag}" "skycoin/public-visor-monitor:${image_tag}" "skycoin/dmsg-monitor:${image_tag}" diff --git a/docker/docker_push.sh b/docker/docker_push.sh index a8d57434..e1e1c568 100755 --- a/docker/docker_push.sh +++ b/docker/docker_push.sh @@ -23,7 +23,6 @@ declare -a images_arr=( "network-monitor" # "node-visualizer" "config-bootstrapper" - "liveness-checker" "vpn-monitor" "public-visor-monitor" "dmsg-monitor" diff --git a/docker/images/address-resolver/Dockerfile b/docker/images/address-resolver/Dockerfile index 197b792f..906fa29a 100755 --- a/docker/images/address-resolver/Dockerfile +++ b/docker/images/address-resolver/Dockerfile @@ -1,7 +1,7 @@ ARG base_image ARG image_tag -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts @@ -12,14 +12,14 @@ RUN go build "${build_opts}" -o /release/address-resolver \ ./cmd/address-resolver -FROM alpine as prod +FROM alpine AS prod COPY --from=builder /release/address-resolver /release/address-resolver ENTRYPOINT ["/release/address-resolver"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh RUN sh -c /release/install-prequisites.sh cert-only \ @@ -28,6 +28,6 @@ RUN sh -c /release/install-prequisites.sh cert-only \ COPY --from=builder /release/address-resolver /release/address-resolver ENTRYPOINT ["/release/address-resolver"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/config-bootstrapper/Dockerfile b/docker/images/config-bootstrapper/Dockerfile index 9e677200..f8a5997c 100644 --- a/docker/images/config-bootstrapper/Dockerfile +++ b/docker/images/config-bootstrapper/Dockerfile @@ -1,7 +1,7 @@ ARG image_tag ARG base_image -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts @@ -11,15 +11,15 @@ WORKDIR /skywire-services RUN go build "${build_opts}" -o /release/config-bootstrapper ./cmd/config-bootstrapper && \ mv /skywire-services/docker/config/config.json /release/config.json -FROM alpine as prod +FROM alpine AS prod COPY --from=builder /release/config-bootstrapper /release/config-bootstrapper COPY --from=builder /release/config.json /release/config.json ENTRYPOINT ["/release/config-bootstrapper"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh RUN sh -c /release/install-prequisites.sh cert-only \ @@ -29,6 +29,6 @@ COPY --from=builder /release/config-bootstrapper /release/config-bootstrapper COPY --from=builder /release/config.json /release/config.json ENTRYPOINT ["/release/config-bootstrapper"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/dmsg-discovery/Dockerfile b/docker/images/dmsg-discovery/Dockerfile index ecdab041..47974e49 100644 --- a/docker/images/dmsg-discovery/Dockerfile +++ b/docker/images/dmsg-discovery/Dockerfile @@ -1,10 +1,10 @@ ARG image_tag ARG base_image -FROM ${base_image} as prod +FROM ${base_image} AS prod -FROM ${base_image} as test +FROM ${base_image} AS test # OS image -FROM ${base_image} as e2e +FROM ${base_image} AS e2e FROM ${image_tag} diff --git a/docker/images/dmsg-discovery/DockerfileInt b/docker/images/dmsg-discovery/DockerfileInt index 27f5e1d5..edee7bd8 100644 --- a/docker/images/dmsg-discovery/DockerfileInt +++ b/docker/images/dmsg-discovery/DockerfileInt @@ -1,9 +1,7 @@ -FROM golang:1.21-alpine AS builder +FROM golang:1.23-alpine AS builder ARG CGO_ENABLED=0 ENV CGO_ENABLED=${CGO_ENABLED} \ - GOOS=linux \ - GOARCH=amd64 \ GO111MODULE=on COPY /tmp/dmsg /dmsg diff --git a/docker/images/dmsg-monitor/Dockerfile b/docker/images/dmsg-monitor/Dockerfile index 85847326..ae9bdb21 100644 --- a/docker/images/dmsg-monitor/Dockerfile +++ b/docker/images/dmsg-monitor/Dockerfile @@ -1,7 +1,7 @@ ARG image_tag ARG base_image -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts @@ -10,16 +10,16 @@ WORKDIR /skywire-services RUN go build "${build_opts}" -o /release/dmsg-monitor ./cmd/dmsg-monitor -FROM alpine as prod +FROM alpine AS prod WORKDIR /release COPY --from=builder /release/dmsg-monitor /release/dmsg-monitor ENTRYPOINT ["/release/dmsg-monitor"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e WORKDIR /release COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh @@ -29,6 +29,6 @@ RUN sh -c /release/install-prequisites.sh cert-only \ COPY --from=builder /release/dmsg-monitor /release/dmsg-monitor ENTRYPOINT ["/release/dmsg-monitor"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/dmsg-server/Dockerfile b/docker/images/dmsg-server/Dockerfile index ecdab041..47974e49 100644 --- a/docker/images/dmsg-server/Dockerfile +++ b/docker/images/dmsg-server/Dockerfile @@ -1,10 +1,10 @@ ARG image_tag ARG base_image -FROM ${base_image} as prod +FROM ${base_image} AS prod -FROM ${base_image} as test +FROM ${base_image} AS test # OS image -FROM ${base_image} as e2e +FROM ${base_image} AS e2e FROM ${image_tag} diff --git a/docker/images/dmsg-server/DockerfileInt b/docker/images/dmsg-server/DockerfileInt index b00c6b60..1a7f3f94 100644 --- a/docker/images/dmsg-server/DockerfileInt +++ b/docker/images/dmsg-server/DockerfileInt @@ -1,9 +1,7 @@ -FROM golang:1.21-alpine AS builder +FROM golang:1.23-alpine AS builder ARG CGO_ENABLED=0 ENV CGO_ENABLED=${CGO_ENABLED} \ - GOOS=linux \ - GOARCH=amd64 \ GO111MODULE=on COPY /tmp/dmsg /dmsg diff --git a/docker/images/liveness-checker/Dockerfile b/docker/images/liveness-checker/Dockerfile deleted file mode 100644 index 639c1f35..00000000 --- a/docker/images/liveness-checker/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -ARG image_tag -ARG base_image - -FROM ${base_image} as builder - -ARG build_opts - -COPY . /skywire-services -WORKDIR /skywire-services - -RUN go build "${build_opts}" -o /release/liveness-checker ./cmd/liveness-checker && \ - go build "${build_opts}" -o /release/vpn-client ./cmd/vpn-lite-client && \ - mv /skywire-services/docker/config/liveness-checker.json /release/liveness-checker.json - -FROM alpine as prod -COPY --from=builder /release/vpn-client /apps/vpn-client -COPY --from=builder /release/liveness-checker /release/liveness-checker -COPY --from=builder /release/liveness-checker.json /release/liveness-checker.json -ENTRYPOINT ["/release/liveness-checker"] - -FROM prod as test - -# OS image -FROM alpine as e2e -WORKDIR /release - -COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh -RUN sh -c /release/install-prequisites.sh cert-only \ - && rm -rf /release/install-prequisites.sh - -COPY --from=builder /release/vpn-client /release/vpn-client -COPY --from=builder /release/liveness-checker /release/liveness-checker -COPY --from=builder /release/liveness-checker.json /release/liveness-checker.json -ENTRYPOINT ["/release/liveness-checker"] - -FROM e2e as integration - -FROM ${image_tag} diff --git a/docker/images/network-monitor/Dockerfile b/docker/images/network-monitor/Dockerfile index 459d346d..a4913d38 100644 --- a/docker/images/network-monitor/Dockerfile +++ b/docker/images/network-monitor/Dockerfile @@ -1,7 +1,7 @@ ARG image_tag ARG base_image -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts @@ -11,16 +11,16 @@ WORKDIR /skywire-services RUN go build "${build_opts}" -o /release/network-monitor ./cmd/network-monitor && \ go build "${build_opts}" -o /release/vpn-client ./cmd/vpn-lite-client -FROM alpine as prod +FROM alpine AS prod WORKDIR /release COPY --from=builder /release/vpn-client /apps/vpn-client COPY --from=builder /release/network-monitor /release/network-monitor ENTRYPOINT ["/release/network-monitor"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e WORKDIR /release COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh @@ -31,6 +31,6 @@ COPY --from=builder /release/vpn-client /release/vpn-client COPY --from=builder /release/network-monitor /release/network-monitor ENTRYPOINT ["/release/network-monitor"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/node-visualizer/Dockerfile b/docker/images/node-visualizer/Dockerfile index d9596753..602d557a 100644 --- a/docker/images/node-visualizer/Dockerfile +++ b/docker/images/node-visualizer/Dockerfile @@ -12,7 +12,7 @@ RUN yarn --cwd ./pkg/node-visualizer/web install && \ mv ./pkg/node-visualizer/web/build/* ./pkg/node-visualizer/api/build -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts # COPY . /skywire-services @@ -21,14 +21,14 @@ WORKDIR /skywire-services RUN go build "${build_opts}" -o /release/node-visualizer ./cmd/node-visualizer -FROM alpine as prod +FROM alpine AS prod COPY --from=builder /release/node-visualizer /release/node-visualizer ENTRYPOINT ["/release/node-visualizer"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh RUN sh -c /release/install-prequisites.sh cert-only \ && rm -rf /release/install-prequisites.sh @@ -36,6 +36,6 @@ RUN sh -c /release/install-prequisites.sh cert-only \ COPY --from=builder /release/node-visualizer /release/node-visualizer ENTRYPOINT ["/release/node-visualizer"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/public-visor-monitor/Dockerfile b/docker/images/public-visor-monitor/Dockerfile index 972a6098..6581b690 100644 --- a/docker/images/public-visor-monitor/Dockerfile +++ b/docker/images/public-visor-monitor/Dockerfile @@ -1,7 +1,7 @@ ARG image_tag ARG base_image -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts @@ -10,14 +10,14 @@ WORKDIR /skywire-services RUN go build "${build_opts}" -o /release/public-visor-monitor ./cmd/public-visor-monitor -FROM alpine as prod +FROM alpine AS prod COPY --from=builder /release/public-visor-monitor /release/public-visor-monitor ENTRYPOINT ["/release/public-visor-monitor"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e WORKDIR /release COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh @@ -27,6 +27,6 @@ RUN sh -c /release/install-prequisites.sh cert-only \ COPY --from=builder /release/public-visor-monitor /release/public-visor-monitor ENTRYPOINT ["/release/public-visor-monitor"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/route-finder/Dockerfile b/docker/images/route-finder/Dockerfile index a1ac9875..e98c1224 100755 --- a/docker/images/route-finder/Dockerfile +++ b/docker/images/route-finder/Dockerfile @@ -1,7 +1,7 @@ ARG image_tag ARG base_image -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts COPY . /skywire-services @@ -9,14 +9,14 @@ WORKDIR /skywire-services RUN go build "${build_opts}" -o /release/route-finder ./cmd/route-finder -FROM alpine as prod +FROM alpine AS prod COPY --from=builder /release/route-finder /release/route-finder ENTRYPOINT ["/release/route-finder"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh RUN sh -c /release/install-prequisites.sh cert-only \ && rm -rf /release/install-prequisites.sh @@ -24,6 +24,6 @@ RUN sh -c /release/install-prequisites.sh cert-only \ COPY --from=builder /release/route-finder /release/route-finder ENTRYPOINT ["/release/route-finder"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/service-discovery/Dockerfile b/docker/images/service-discovery/Dockerfile index 70b70018..13e09b01 100644 --- a/docker/images/service-discovery/Dockerfile +++ b/docker/images/service-discovery/Dockerfile @@ -1,15 +1,13 @@ ARG image_tag ARG base_image -FROM ${base_image} as service-discovery-build +FROM ${base_image} AS service-discovery-build ARG build_opts RUN apk --no-cache add bash curl ARG CGO_ENABLED=0 ENV CGO_ENABLED=${CGO_ENABLED} \ - GOOS=linux \ - GOARCH=amd64 \ GO111MODULE=on COPY /docker/common/install-prequisites.sh /install-prequisites.sh @@ -20,7 +18,7 @@ WORKDIR /skycoin-service-discovery RUN go build "${build_opts}" -o /release/service-discovery ./cmd/service-discovery -FROM alpine as prod +FROM alpine AS prod COPY --from=service-discovery-build /install-prequisites.sh /release/install-prequisites.sh RUN sh -c /release/install-prequisites.sh cert-only \ @@ -30,9 +28,9 @@ COPY --from=service-discovery-build /release/* /release/ WORKDIR /release ENTRYPOINT [ "/release/service-discovery" ] -FROM prod as test +FROM prod AS test -FROM alpine as e2e +FROM alpine AS e2e COPY --from=service-discovery-build /install-prequisites.sh /release/install-prequisites.sh RUN sh -c /release/install-prequisites.sh cert-only \ @@ -42,6 +40,6 @@ COPY --from=service-discovery-build /release /release WORKDIR /release ENTRYPOINT [ "/release/service-discovery" ] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/setup-node/Dockerfile b/docker/images/setup-node/Dockerfile index 63195042..4ed77565 100755 --- a/docker/images/setup-node/Dockerfile +++ b/docker/images/setup-node/Dockerfile @@ -1,7 +1,7 @@ ARG image_tag ARG base_image -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts @@ -11,17 +11,17 @@ WORKDIR /skywire-services RUN go build "${build_opts}" -o /release/setup-node ./cmd/setup-node && \ mv ./docker/config/setup-node.json /release/setup-node.json -FROM alpine as prod +FROM alpine AS prod WORKDIR /release COPY --from=builder /release/setup-node /release/setup-node COPY --from=builder /release/setup-node.json /release/setup-node.json ENTRYPOINT ["/release/setup-node"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e WORKDIR /release COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh @@ -32,6 +32,6 @@ COPY --from=builder /release/setup-node /release/setup-node COPY --from=builder /release/setup-node.json /release/setup-node.json ENTRYPOINT ["/release/setup-node"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/skysocks-monitor/Dockerfile b/docker/images/skysocks-monitor/Dockerfile index a894590d..ffb70c02 100644 --- a/docker/images/skysocks-monitor/Dockerfile +++ b/docker/images/skysocks-monitor/Dockerfile @@ -1,7 +1,7 @@ ARG image_tag ARG base_image -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts @@ -11,15 +11,15 @@ WORKDIR /skywire-services RUN go build "${build_opts}" -o /release/skysocks-monitor ./cmd/skysocks-monitor && \ go build "${build_opts}" -o /release/skysocks-client ./cmd/skysocks-lite-client -FROM alpine as prod +FROM alpine AS prod COPY --from=builder /release/skysocks-client /apps/skysocks-client COPY --from=builder /release/skysocks-monitor /release/skysocks-monitor ENTRYPOINT ["/release/skysocks-monitor"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e WORKDIR /release COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh @@ -30,6 +30,6 @@ COPY --from=builder /release/skysocks-client /release/skysocks-client COPY --from=builder /release/skysocks-monitor /release/skysocks-monitor ENTRYPOINT ["/release/skysocks-monitor"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/skywire-visor/Dockerfile b/docker/images/skywire-visor/Dockerfile index ed5b3e1e..e1b66131 100755 --- a/docker/images/skywire-visor/Dockerfile +++ b/docker/images/skywire-visor/Dockerfile @@ -1,7 +1,7 @@ ARG image_tag=e2e ARG base=alpine -FROM golang:1.21-alpine as builder +FROM golang:1.23-alpine AS builder ARG BUILDINFO_LDFLAGS ARG CGO_ENABLED=0 @@ -18,7 +18,7 @@ RUN apk add --no-cache make git build-base && \ make build-race ## Resulting image -FROM ${base} as visor-runner +FROM ${base} AS visor-runner COPY --from=builder /skywire/docker/images/visor/install-preq.sh /release/install-preq.sh COPY --from=builder /release /release @@ -33,10 +33,10 @@ STOPSIGNAL SIGINT ENTRYPOINT [ "/release/skywire" ] # default target -FROM visor-runner as prod +FROM visor-runner AS prod -FROM visor-runner as test +FROM visor-runner AS test -FROM visor-runner as e2e +FROM visor-runner AS e2e FROM ${image_tag} diff --git a/docker/images/skywire-visor/DockerfileInt b/docker/images/skywire-visor/DockerfileInt index b1022e56..c2caf5bb 100644 --- a/docker/images/skywire-visor/DockerfileInt +++ b/docker/images/skywire-visor/DockerfileInt @@ -1,7 +1,7 @@ ARG image_tag=e2e ARG base=alpine -FROM golang:1.21-alpine as builder +FROM golang:1.23-alpine AS builder ARG BUILDINFO_LDFLAGS ARG CGO_ENABLED=0 @@ -17,7 +17,7 @@ RUN apk add --no-cache make git build-base && \ make build-race ## Resulting image -FROM ${base} as visor-runner +FROM ${base} AS visor-runner COPY --from=builder /skywire/docker/images/visor/install-preq.sh /release/install-preq.sh COPY --from=builder /release /release @@ -31,12 +31,12 @@ STOPSIGNAL SIGINT ENTRYPOINT [ "/release/skywire" ] # default target -FROM visor-runner as prod +FROM visor-runner AS prod -FROM visor-runner as test +FROM visor-runner AS test -FROM visor-runner as e2e +FROM visor-runner AS e2e -FROM visor-runner as integration +FROM visor-runner AS integration FROM ${image_tag} diff --git a/docker/images/tpd-monitor/Dockerfile b/docker/images/tpd-monitor/Dockerfile index c3930902..76421d65 100644 --- a/docker/images/tpd-monitor/Dockerfile +++ b/docker/images/tpd-monitor/Dockerfile @@ -1,7 +1,7 @@ ARG image_tag ARG base_image -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts @@ -10,14 +10,14 @@ WORKDIR /skywire-services RUN go build "${build_opts}" -o /release/tpd-monitor ./cmd/tpd-monitor -FROM alpine as prod +FROM alpine AS prod COPY --from=builder /release/tpd-monitor /release/tpd-monitor ENTRYPOINT ["/release/tpd-monitor"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e WORKDIR /release COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh @@ -27,6 +27,6 @@ RUN sh -c /release/install-prequisites.sh cert-only \ COPY --from=builder /release/tpd-monitor /release/tpd-monitor ENTRYPOINT ["/release/tpd-monitor"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/transport-discovery/Dockerfile b/docker/images/transport-discovery/Dockerfile index 4cccb596..57f19c3b 100755 --- a/docker/images/transport-discovery/Dockerfile +++ b/docker/images/transport-discovery/Dockerfile @@ -1,7 +1,7 @@ ARG base_image ARG image_tag -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts @@ -12,14 +12,14 @@ RUN go build "${build_opts}" -o /release/transport-discovery \ ./cmd/transport-discovery -FROM alpine as prod +FROM alpine AS prod COPY --from=builder /release/transport-discovery /release/transport-discovery ENTRYPOINT ["/release/transport-discovery"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh RUN sh -c /release/install-prequisites.sh cert-only \ @@ -28,6 +28,6 @@ RUN sh -c /release/install-prequisites.sh cert-only \ COPY --from=builder /release/transport-discovery /release/transport-discovery ENTRYPOINT ["/release/transport-discovery"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/transport-setup/Dockerfile b/docker/images/transport-setup/Dockerfile index 17cc95b7..0065edcc 100755 --- a/docker/images/transport-setup/Dockerfile +++ b/docker/images/transport-setup/Dockerfile @@ -1,7 +1,7 @@ ARG image_tag ARG base_image -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts @@ -11,17 +11,17 @@ WORKDIR /skywire-services RUN go build "${build_opts}" -o /release/transport-setup ./cmd/transport-setup && \ mv ./docker/config/transport-setup.json /release/transport-setup.json -FROM alpine as prod +FROM alpine AS prod WORKDIR /release COPY --from=builder /release/transport-setup /release/transport-setup COPY --from=builder /release/transport-setup.json /release/transport-setup.json ENTRYPOINT ["/release/transport-setup"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e WORKDIR /release COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh @@ -32,6 +32,6 @@ COPY --from=builder /release/transport-setup /release/transport-setup COPY --from=builder /release/transport-setup.json /release/transport-setup.json ENTRYPOINT ["/release/transport-setup"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/uptime-tracker/Dockerfile b/docker/images/uptime-tracker/Dockerfile index 02930b00..9f0fa6b0 100644 --- a/docker/images/uptime-tracker/Dockerfile +++ b/docker/images/uptime-tracker/Dockerfile @@ -1,7 +1,7 @@ ARG base_image ARG image_tag -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts @@ -12,14 +12,14 @@ RUN go build "${build_opts}" -o /release/uptime-tracker \ ./cmd/uptime-tracker -FROM alpine as prod +FROM alpine AS prod COPY --from=builder /release/uptime-tracker /release/uptime-tracker ENTRYPOINT ["/release/uptime-tracker"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh RUN sh -c /release/install-prequisites.sh cert-only \ @@ -28,6 +28,6 @@ RUN sh -c /release/install-prequisites.sh cert-only \ COPY --from=builder /release/uptime-tracker /release/uptime-tracker ENTRYPOINT ["/release/uptime-tracker"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/docker/images/vpn-monitor/Dockerfile b/docker/images/vpn-monitor/Dockerfile index 5f110e1e..289dd090 100644 --- a/docker/images/vpn-monitor/Dockerfile +++ b/docker/images/vpn-monitor/Dockerfile @@ -1,7 +1,7 @@ ARG image_tag ARG base_image -FROM ${base_image} as builder +FROM ${base_image} AS builder ARG build_opts @@ -11,15 +11,15 @@ WORKDIR /skywire-services RUN go build "${build_opts}" -o /release/vpn-monitor ./cmd/vpn-monitor && \ go build "${build_opts}" -o /release/vpn-client ./cmd/vpn-lite-client -FROM alpine as prod +FROM alpine AS prod COPY --from=builder /release/vpn-client /apps/vpn-client COPY --from=builder /release/vpn-monitor /release/vpn-monitor ENTRYPOINT ["/release/vpn-monitor"] -FROM prod as test +FROM prod AS test # OS image -FROM alpine as e2e +FROM alpine AS e2e WORKDIR /release COPY ./docker/common/install-prequisites.sh /release/install-prequisites.sh @@ -30,6 +30,6 @@ COPY --from=builder /release/vpn-client /release/vpn-client COPY --from=builder /release/vpn-monitor /release/vpn-monitor ENTRYPOINT ["/release/vpn-monitor"] -FROM e2e as integration +FROM e2e AS integration FROM ${image_tag} diff --git a/pkg/dmsg-monitor/api/api.go b/pkg/dmsg-monitor/api/api.go new file mode 100644 index 00000000..d377aafb --- /dev/null +++ b/pkg/dmsg-monitor/api/api.go @@ -0,0 +1,450 @@ +// Package api pkg/dmsg-monitor/api.go +package api + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "math/rand" + "net/http" + "net/url" + "strings" + "sync" + "time" + + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" + "github.com/sirupsen/logrus" + "github.com/skycoin/skywire-utilities/pkg/buildinfo" + "github.com/skycoin/skywire-utilities/pkg/cipher" + "github.com/skycoin/skywire-utilities/pkg/httputil" + "github.com/skycoin/skywire-utilities/pkg/logging" + utilenv "github.com/skycoin/skywire-utilities/pkg/skyenv" + "github.com/skycoin/skywire/pkg/app/appserver" + "github.com/skycoin/skywire/pkg/visor" + "github.com/skycoin/skywire/pkg/visor/visorconfig" +) + +// API register all the API endpoints. +// It implements a net/http.Handler. +type API struct { + http.Handler + + Visor *visor.Visor + + dmsgURL string + utURL string + logger logging.Logger + dMu sync.RWMutex + startedAt time.Time + + nmPk cipher.PubKey + nmSign cipher.Sig + batchSize int + whitelistedPKs map[string]bool +} + +// DMSGMonitorConfig is struct for Keys and Sign value of dmsg monitor +type DMSGMonitorConfig struct { + PK cipher.PubKey + Sign cipher.Sig + BatchSize int +} + +// ServicesURLs is struct for organize URL of services +type ServicesURLs struct { + DMSG string + UT string +} + +// HealthCheckResponse is struct of /health endpoint +type HealthCheckResponse struct { + BuildInfo *buildinfo.Info `json:"build_info,omitempty"` + StartedAt time.Time `json:"started_at,omitempty"` +} + +// Error is the object returned to the client when there's an error. +type Error struct { + Error string `json:"error"` +} + +// New returns a new *chi.Mux object, which can be started as a server +func New(logger *logging.Logger, srvURLs ServicesURLs, monitorConfig DMSGMonitorConfig) *API { + + api := &API{ + dmsgURL: srvURLs.DMSG, + utURL: srvURLs.UT, + logger: *logger, + startedAt: time.Now(), + nmPk: monitorConfig.PK, + nmSign: monitorConfig.Sign, + batchSize: monitorConfig.BatchSize, + whitelistedPKs: whitelistedPKs(), + } + r := chi.NewRouter() + + r.Use(middleware.RequestID) + r.Use(middleware.RealIP) + r.Use(middleware.Logger) + r.Use(middleware.Recoverer) + r.Use(httputil.SetLoggerMiddleware(logger)) + r.Get("/health", api.health) + api.Handler = r + + return api +} + +func (api *API) health(w http.ResponseWriter, r *http.Request) { + info := buildinfo.Get() + api.writeJSON(w, r, http.StatusOK, HealthCheckResponse{ + BuildInfo: info, + StartedAt: api.startedAt, + }) +} + +func (api *API) writeJSON(w http.ResponseWriter, r *http.Request, code int, object interface{}) { + jsonObject, err := json.Marshal(object) + if err != nil { + api.log(r).WithError(err).Errorf("failed to encode json response") + w.WriteHeader(http.StatusInternalServerError) + + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(code) + + _, err = w.Write(jsonObject) + if err != nil { + api.log(r).WithError(err).Errorf("failed to write json response") + } +} + +func (api *API) log(r *http.Request) logrus.FieldLogger { + return httputil.GetLogger(r) +} + +// InitDeregistrationLoop is function which runs periodic background tasks of API. +func (api *API) InitDeregistrationLoop(ctx context.Context, conf *visorconfig.V1, sleepDeregistration time.Duration) { + // Start a visor + api.startVisor(ctx, conf) + + for { + select { + case <-ctx.Done(): + return + default: + api.deregister() + time.Sleep(sleepDeregistration * time.Minute) + } + } +} + +// deregister use as routine to deregister old/dead entries in the network +func (api *API) deregister() { + api.logger.Info("Deregistration routine start.") + defer api.dMu.Unlock() + api.dMu.Lock() + + // get uptimes data to check online/offline of visor based on uptime tracker + uptimes, err := getUptimeTracker(api.utURL) + if err != nil { + api.logger.Warnf("Error occur during get uptime tracker status list due to %s", err) + return + } + + api.dmsgDeregistration(uptimes) + + api.logger.Info("Deregistration routine completed.") +} + +// dmsgDeregistration is a routine to deregister dead dmsg entries in dmsg discovery +func (api *API) dmsgDeregistration(uptimes map[string]bool) { + api.logger.Info("DMSGD Deregistration started.") + + // get list of all dmsg clients, not servers + clients, err := getClients(api.dmsgURL) + if err != nil { + api.logger.Warnf("Error occur during get dmsg clients list due to %s", err) + return + } + //randomize the order of the dmsg entries + rand.Shuffle(len(clients), func(i, j int) { + clients[i], clients[j] = clients[j], clients[i] + }) + // check dmsg clients either alive or dead + checkerConfig := dmsgCheckerConfig{ + wg: new(sync.WaitGroup), + locker: new(sync.Mutex), + uptimes: uptimes, + transport: "dmsg", + } + deadDmsg := []string{} + var tmpBatchSize, deadDmsgCount int + for i, client := range clients { + if _, ok := api.whitelistedPKs[client]; !ok { + checkerConfig.wg.Add(1) + checkerConfig.client = client + go api.dmsgChecker(checkerConfig, &deadDmsg) + } + tmpBatchSize++ + if tmpBatchSize == api.batchSize || i == len(clients)-1 { + checkerConfig.wg.Wait() + // deregister clients from dmsg-discovery + if len(deadDmsg) > 0 { + api.dmsgDeregister(deadDmsg) + deadDmsgCount += len(deadDmsg) + } + deadDmsg = []string{} + tmpBatchSize = 0 + } + } + + api.logger.WithField("Number of dead DMSG entries", deadDmsgCount).Info("DMSGD Deregistration completed.") +} + +func (api *API) dmsgChecker(cfg dmsgCheckerConfig, deadDmsg *[]string) { + defer cfg.wg.Done() + + key := cipher.PubKey{} + err := key.UnmarshalText([]byte(cfg.client)) + if err != nil { + api.logger.Warnf("Error marshaling key: %s", err) + return + } + + var trp bool + retrier := 3 + for retrier > 0 { + tp, err := api.Visor.AddTransport(key, cfg.transport, time.Second*3) + if err != nil { + api.logger.WithField("Retry", 4-retrier).WithError(err).Warnf("Failed to establish %v transport to %v", cfg.transport, key) + retrier-- + if strings.Contains(err.Error(), "unknown network type") { + trp = true + retrier = 0 + } + } else { + api.logger.Infof("Established %v transport to %v", cfg.transport, key) + trp = true + err = api.Visor.RemoveTransport(tp.ID) + if err != nil { + api.logger.Warnf("Error removing %v transport of %v: %v", cfg.transport, key, err) + } + retrier = 0 + } + } + + if !trp { + if status, ok := cfg.uptimes[key.Hex()]; !ok || !status { + cfg.locker.Lock() + *deadDmsg = append(*deadDmsg, key.Hex()) + cfg.locker.Unlock() + } + } +} + +func (api *API) dmsgDeregister(keys []string) { + err := api.deregisterRequest(keys, api.dmsgURL+"/dmsg-discovery/deregister", "dmsg discovery") + if err != nil { + api.logger.Warn(err) + return + } + api.logger.Info("Deregister request send to DSMGD") +} + +type dmsgCheckerConfig struct { + client string + transport string + uptimes map[string]bool + wg *sync.WaitGroup + locker *sync.Mutex +} + +// deregisterRequest is dereigstration handler for all services +func (api *API) deregisterRequest(keys []string, rawReqURL, service string) error { + reqURL, err := url.Parse(rawReqURL) + if err != nil { + return fmt.Errorf("Error on parsing deregistration URL : %v", err) + } + + jsonData, err := json.Marshal(keys) + if err != nil { + return fmt.Errorf("Error on parsing deregistration keys : %v", err) + } + body := bytes.NewReader(jsonData) + + req := &http.Request{ + Method: "DELETE", + URL: reqURL, + Header: map[string][]string{ + "NM-PK": {api.nmPk.Hex()}, + "NM-Sign": {api.nmSign.Hex()}, + }, + Body: io.NopCloser(body), + } + + res, err := http.DefaultClient.Do(req) + if err != nil { + return fmt.Errorf("Error on send deregistration request : %s", err) + } + defer res.Body.Close() //nolint + + if res.StatusCode != http.StatusOK { + return fmt.Errorf("Error deregister keys from %s : %s", service, err) + } + + return nil +} + +type clientList []string + +func getClients(dmsgURL string) (data clientList, err error) { + res, err := http.Get(dmsgURL + "/dmsg-discovery/visorEntries") //nolint + + if err != nil { + return nil, err + } + + body, err := io.ReadAll(res.Body) + + if err != nil { + return nil, err + } + + err = json.Unmarshal(body, &data) + if err != nil { + return nil, err + } + return data, nil +} + +func getUptimeTracker(utURL string) (map[string]bool, error) { + response := make(map[string]bool) + res, err := http.Get(utURL) //nolint + if err != nil { + return response, err + } + + body, err := io.ReadAll(res.Body) + if err != nil { + return response, err + } + var data []uptimes + err = json.Unmarshal(body, &data) + if err != nil { + return response, err + } + + for _, visor := range data { + response[visor.Key] = visor.Online + } + + return response, nil +} + +type uptimes struct { + Key string `json:"key"` + Online bool `json:"online"` +} + +func (api *API) startVisor(ctx context.Context, conf *visorconfig.V1) { + conf.SetLogger(logging.NewMasterLogger()) + v, ok := visor.NewVisor(ctx, conf) + if !ok { + api.logger.Fatal("Failed to start visor.") + } + api.Visor = v +} + +// InitConfig to initilise config +func InitConfig(confPath string, mLog *logging.MasterLogger) *visorconfig.V1 { + log := mLog.PackageLogger("network_monitor:config") + log.Info("Reading config from file.") + log.WithField("filepath", confPath).Info() + + oldConf, err := visorconfig.ReadFile(confPath) + if err != nil { + log.WithError(err).Fatal("Failed to read config file.") + } + var testEnv bool + if oldConf.Dmsg.Discovery == utilenv.TestDmsgDiscAddr { + testEnv = true + } + // have same services as old config + services := &visorconfig.Services{ + DmsgDiscovery: oldConf.Dmsg.Discovery, + TransportDiscovery: oldConf.Transport.Discovery, + AddressResolver: oldConf.Transport.AddressResolver, + RouteFinder: oldConf.Routing.RouteFinder, + RouteSetupNodes: oldConf.Routing.RouteSetupNodes, + UptimeTracker: oldConf.UptimeTracker.Addr, + ServiceDiscovery: oldConf.Launcher.ServiceDisc, + } + // update oldconfig + conf, err := visorconfig.MakeDefaultConfig(mLog, &oldConf.SK, false, false, testEnv, false, false, confPath, "", services) + if err != nil { + log.WithError(err).Fatal("Failed to create config.") + } + + // have the same apps that the old config had + var newConfLauncherApps []appserver.AppConfig + for _, app := range conf.Launcher.Apps { + for _, oldApp := range oldConf.Launcher.Apps { + if app.Name == oldApp.Name { + newConfLauncherApps = append(newConfLauncherApps, app) + } + } + } + conf.Launcher.Apps = newConfLauncherApps + + conf.Version = oldConf.Version + conf.LocalPath = oldConf.LocalPath + conf.Launcher.BinPath = oldConf.Launcher.BinPath + conf.Launcher.ServerAddr = oldConf.Launcher.ServerAddr + conf.CLIAddr = oldConf.CLIAddr + conf.Transport.TransportSetupPKs = oldConf.Transport.TransportSetupPKs + + // following services are not needed + conf.STCP = nil + conf.Dmsgpty = nil + conf.Transport.PublicAutoconnect = false + + // save the config file + if err := conf.Flush(); err != nil { + log.WithError(err).Fatal("Failed to flush config to file.") + } + + return conf +} + +func whitelistedPKs() map[string]bool { + whitelistedPKs := make(map[string]bool) + for _, pk := range strings.Split(utilenv.NetworkMonitorPKs, ",") { + whitelistedPKs[pk] = true + } + for _, pk := range strings.Split(utilenv.TestNetworkMonitorPKs, ",") { + whitelistedPKs[pk] = true + } + for _, pk := range strings.Split(utilenv.RouteSetupPKs, ",") { + whitelistedPKs[pk] = true + } + for _, pk := range strings.Split(utilenv.TestRouteSetupPKs, ",") { + whitelistedPKs[pk] = true + } + for _, pk := range strings.Split(utilenv.TPSetupPKs, ",") { + whitelistedPKs[pk] = true + } + for _, pk := range strings.Split(utilenv.TestTPSetupPKs, ",") { + whitelistedPKs[pk] = true + } + for _, pk := range strings.Split(utilenv.SurveyWhitelistPKs, ",") { + whitelistedPKs[pk] = true + } + for _, pk := range strings.Split(utilenv.RewardSystemPKs, ",") { + whitelistedPKs[pk] = true + } + return whitelistedPKs +}