diff --git a/internal/app/diun.go b/internal/app/diun.go index 47a6b41f7..064456b8c 100644 --- a/internal/app/diun.go +++ b/internal/app/diun.go @@ -18,6 +18,7 @@ import ( kubernetesPrd "github.com/crazy-max/diun/v4/internal/provider/kubernetes" nomadPrd "github.com/crazy-max/diun/v4/internal/provider/nomad" swarmPrd "github.com/crazy-max/diun/v4/internal/provider/swarm" + "github.com/crazy-max/diun/v4/pkg/utl" "github.com/crazy-max/gohealthchecks" "github.com/dromara/carbon/v2" "github.com/panjf2000/ants/v2" @@ -30,10 +31,11 @@ type Diun struct { meta model.Meta cfg *config.Config - db *db.Client - grpc *grpc.Client - hc *gohealthchecks.Client - notif *notif.Client + db *db.Client + grpc *grpc.Client + hc *gohealthchecks.Client + hcUUID string + notif *notif.Client cron *cron.Cron jobID cron.EntryID @@ -77,6 +79,10 @@ func New(meta model.Meta, cfg *config.Config, grpcAuthority string) (*Diun, erro return nil, errors.Wrap(err, "cannot parse Healthchecks base URL") } } + diun.hcUUID, err = utl.GetSecret(cfg.Watch.Healthchecks.UUID, cfg.Watch.Healthchecks.UUIDFile) + if err != nil { + return nil, errors.Wrap(err, "cannot retrieve Healthchecks UUID") + } diun.hc = gohealthchecks.NewClient(&gohealthchecks.ClientOptions{ BaseURL: hcBaseURL, }) diff --git a/internal/app/hc.go b/internal/app/hc.go index 1c039f1a4..c57b2abc6 100644 --- a/internal/app/hc.go +++ b/internal/app/hc.go @@ -16,7 +16,7 @@ func (di *Diun) HealthchecksStart() { } if err := di.hc.Start(context.Background(), gohealthchecks.PingingOptions{ - UUID: di.cfg.Watch.Healthchecks.UUID, + UUID: di.hcUUID, }); err != nil { log.Error().Err(err).Msgf("Cannot send Healthchecks start event") } @@ -40,7 +40,7 @@ func (di *Diun) HealthchecksSuccess(entries *model.NotifEntries) { } if err := di.hc.Success(context.Background(), gohealthchecks.PingingOptions{ - UUID: di.cfg.Watch.Healthchecks.UUID, + UUID: di.hcUUID, Logs: logsBuf.String(), }); err != nil { log.Error().Err(err).Msgf("Cannot send Healthchecks success event") @@ -53,7 +53,7 @@ func (di *Diun) HealthchecksFail(logs string) { } if err := di.hc.Fail(context.Background(), gohealthchecks.PingingOptions{ - UUID: di.cfg.Watch.Healthchecks.UUID, + UUID: di.hcUUID, Logs: logs, }); err != nil { log.Error().Err(err).Msgf("Cannot send Healthchecks fail event") diff --git a/internal/config/config.go b/internal/config/config.go index e8f5671d4..69bdc2706 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -70,7 +70,7 @@ func (cfg *Config) validate() error { } } - if cfg.Watch.Healthchecks != nil && len(cfg.Watch.Healthchecks.UUID) == 0 { + if cfg.Watch.Healthchecks != nil && len(cfg.Watch.Healthchecks.UUID) == 0 && len(cfg.Watch.Healthchecks.UUIDFile) == 0 { return errors.New("healthchecks UUID is required") } diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 0cc43157a..954dd6514 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -35,6 +35,32 @@ func TestLoadFile(t *testing.T) { cfg: "./fixtures/config.err.hc.yml", wantErr: true, }, + { + name: "Success with healthchecks uuidFile", + cfg: "./fixtures/config.hc.uuidfile.yml", + wantData: &Config{ + Db: (&model.Db{}).GetDefaults(), + Watch: &model.Watch{ + Workers: 10, + Jitter: utl.NewDuration(30 * time.Second), + FirstCheckNotif: utl.NewFalse(), + RunOnStartup: utl.NewTrue(), + CompareDigest: utl.NewTrue(), + Healthchecks: &model.Healthchecks{ + BaseURL: "https://hc-ping.com/", + UUIDFile: "./fixtures/run_secrets_uuid", + }, + }, + Defaults: (&model.Defaults{}).GetDefaults(), + Providers: &model.Providers{ + Docker: &model.PrdDocker{ + TLSVerify: utl.NewTrue(), + WatchByDefault: utl.NewFalse(), + WatchStopped: utl.NewFalse(), + }, + }, + }, + }, { name: "Fail on no provider", cfg: "./fixtures/config.err.provider.yml", @@ -290,6 +316,35 @@ func TestLoadEnv(t *testing.T) { expected: nil, wantErr: true, }, + { + desc: "healthchecks with UUIDFILE env var", + environ: []string{ + "DIUN_WATCH_HEALTHCHECKS_UUIDFILE=./fixtures/run_secrets_uuid", + "DIUN_PROVIDERS_DOCKER=true", + }, + expected: &Config{ + Db: (&model.Db{}).GetDefaults(), + Watch: &model.Watch{ + Workers: 10, + Jitter: utl.NewDuration(30 * time.Second), + FirstCheckNotif: utl.NewFalse(), + RunOnStartup: utl.NewTrue(), + CompareDigest: utl.NewTrue(), + Healthchecks: &model.Healthchecks{ + UUIDFile: "./fixtures/run_secrets_uuid", + }, + }, + Defaults: (&model.Defaults{}).GetDefaults(), + Providers: &model.Providers{ + Docker: &model.PrdDocker{ + TLSVerify: utl.NewTrue(), + WatchByDefault: utl.NewFalse(), + WatchStopped: utl.NewFalse(), + }, + }, + }, + wantErr: false, + }, { desc: "docker provider", environ: []string{ diff --git a/internal/config/fixtures/config.hc.uuidfile.yml b/internal/config/fixtures/config.hc.uuidfile.yml new file mode 100644 index 000000000..b0c8ce2cf --- /dev/null +++ b/internal/config/fixtures/config.hc.uuidfile.yml @@ -0,0 +1,7 @@ +watch: + healthchecks: + baseURL: https://hc-ping.com/ + uuidFile: ./fixtures/run_secrets_uuid + +providers: + docker: {} diff --git a/internal/config/fixtures/run_secrets_uuid b/internal/config/fixtures/run_secrets_uuid new file mode 100644 index 000000000..36a27d757 --- /dev/null +++ b/internal/config/fixtures/run_secrets_uuid @@ -0,0 +1 @@ +5bf66975-d4c7-4bf5-bcc8-b8d8a82ea278 \ No newline at end of file diff --git a/internal/model/watch_healthchecks.go b/internal/model/watch_healthchecks.go index 7d472e6ee..01853cad2 100644 --- a/internal/model/watch_healthchecks.go +++ b/internal/model/watch_healthchecks.go @@ -2,8 +2,9 @@ package model // Healthchecks holds data necessary for Healthchecks configuration type Healthchecks struct { - BaseURL string `yaml:"baseURL,omitempty" json:"baseURL,omitempty"` - UUID string `yaml:"uuid,omitempty" json:"uuid,omitempty" validate:"required"` + BaseURL string `yaml:"baseURL,omitempty" json:"baseURL,omitempty"` + UUID string `yaml:"uuid,omitempty" json:"uuid,omitempty" validate:"omitempty"` + UUIDFile string `yaml:"uuidFile,omitempty" json:"uuidFile,omitempty" validate:"omitempty,file"` } // GetDefaults gets the default values