From 656de420bb6533e7e08b28c839dc0f4e409de34b Mon Sep 17 00:00:00 2001 From: Kyle Felter Date: Tue, 30 Jun 2026 11:09:25 -0500 Subject: [PATCH] feat: Add machine health report override endpoints Signed-off-by: Kyle Felter --- rest-api/api/pkg/api/handler/adminmachine.go | 100 ++++ rest-api/api/pkg/api/handler/adminops_test.go | 204 ++++++++ .../api/pkg/api/handler/healthoverride.go | 163 ++++++ rest-api/api/pkg/api/model/adminops_test.go | 85 +++ rest-api/api/pkg/api/model/healthoverride.go | 258 ++++++++++ rest-api/api/pkg/api/routes.go | 15 + rest-api/api/pkg/api/routes_test.go | 7 +- rest-api/openapi/spec.yaml | 229 ++++++++ rest-api/sdk/standard/api_health_report.go | 487 ++++++++++++++++++ rest-api/sdk/standard/client.go | 3 + .../model_machine_health_report_entry.go | 335 ++++++++++++ ...del_machine_health_report_list_response.go | 185 +++++++ ...model_machine_health_report_probe_alert.go | 335 ++++++++++++ ...del_machine_health_report_probe_success.go | 194 +++++++ ...l_machine_health_report_remove_response.go | 186 +++++++ .../model_machine_health_report_response.go | 185 +++++++ 16 files changed, 2970 insertions(+), 1 deletion(-) create mode 100644 rest-api/api/pkg/api/handler/adminmachine.go create mode 100644 rest-api/api/pkg/api/handler/adminops_test.go create mode 100644 rest-api/api/pkg/api/handler/healthoverride.go create mode 100644 rest-api/api/pkg/api/model/adminops_test.go create mode 100644 rest-api/api/pkg/api/model/healthoverride.go create mode 100644 rest-api/sdk/standard/api_health_report.go create mode 100644 rest-api/sdk/standard/model_machine_health_report_entry.go create mode 100644 rest-api/sdk/standard/model_machine_health_report_list_response.go create mode 100644 rest-api/sdk/standard/model_machine_health_report_probe_alert.go create mode 100644 rest-api/sdk/standard/model_machine_health_report_probe_success.go create mode 100644 rest-api/sdk/standard/model_machine_health_report_remove_response.go create mode 100644 rest-api/sdk/standard/model_machine_health_report_response.go diff --git a/rest-api/api/pkg/api/handler/adminmachine.go b/rest-api/api/pkg/api/handler/adminmachine.go new file mode 100644 index 0000000000..93a678a535 --- /dev/null +++ b/rest-api/api/pkg/api/handler/adminmachine.go @@ -0,0 +1,100 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package handler + +import ( + "context" + "errors" + "fmt" + "net/http" + + "github.com/labstack/echo/v4" + "github.com/rs/zerolog" + tClient "go.temporal.io/sdk/client" + + "github.com/NVIDIA/infra-controller/rest-api/api/internal/config" + "github.com/NVIDIA/infra-controller/rest-api/api/pkg/api/handler/util/common" + sc "github.com/NVIDIA/infra-controller/rest-api/api/pkg/client/site" + auth "github.com/NVIDIA/infra-controller/rest-api/auth/pkg/authorization" + cutil "github.com/NVIDIA/infra-controller/rest-api/common/pkg/util" + cdb "github.com/NVIDIA/infra-controller/rest-api/db/pkg/db" + cdbm "github.com/NVIDIA/infra-controller/rest-api/db/pkg/db/model" +) + +type adminMachineBase struct { + dbSession *cdb.Session + scp *sc.ClientPool + cfg *config.Config + tracerSpan *cutil.TracerSpan +} + +func (b adminMachineBase) authorizeMachine( + ctx context.Context, + c echo.Context, + logger zerolog.Logger, + org string, + dbUser *cdbm.User, + machineID string, +) (tClient.Client, string, *cdbm.Machine, error) { + if dbUser == nil { + logger.Error().Msg("invalid User object found in request context") + return nil, "", nil, cutil.NewAPIErrorResponse(c, http.StatusInternalServerError, "Failed to retrieve current user", nil) + } + if machineID == "" { + return nil, "", nil, cutil.NewAPIErrorResponse(c, http.StatusBadRequest, "Machine ID is required", nil) + } + + ok, err := auth.ValidateOrgMembership(dbUser, org) + if !ok { + if err != nil { + logger.Error().Err(err).Msg("error validating org membership for User in request") + } else { + logger.Warn().Msg("could not validate org membership for user, access denied") + } + return nil, "", nil, cutil.NewAPIErrorResponse(c, http.StatusForbidden, fmt.Sprintf("Failed to validate membership for org: %s", org), nil) + } + + if ok := auth.ValidateUserRoles(dbUser, org, nil, auth.ProviderAdminRole); !ok { + logger.Warn().Msg("user does not have Provider Admin role, access denied") + return nil, "", nil, cutil.NewAPIErrorResponse(c, http.StatusForbidden, "User does not have Provider Admin role with org", nil) + } + + provider, err := common.GetInfrastructureProviderForOrg(ctx, nil, b.dbSession, org) + if err != nil { + logger.Warn().Err(err).Msg("error getting infrastructure provider for org") + return nil, "", nil, cutil.NewAPIErrorResponse(c, http.StatusBadRequest, "Failed to retrieve Infrastructure Provider for org", nil) + } + + machine, err := cdbm.NewMachineDAO(b.dbSession).GetByID(ctx, nil, machineID, nil, false) + if err != nil { + if errors.Is(err, cdb.ErrDoesNotExist) { + return nil, "", nil, cutil.NewAPIErrorResponse(c, http.StatusNotFound, "Could not find Machine with specified ID", nil) + } + logger.Error().Err(err).Msg("error retrieving Machine DB entity") + return nil, "", nil, cutil.NewAPIErrorResponse(c, http.StatusInternalServerError, "Could not retrieve Machine", nil) + } + + if machine.InfrastructureProviderID != provider.ID { + return nil, "", nil, cutil.NewAPIErrorResponse(c, http.StatusForbidden, "Machine doesn't belong to org's Infrastructure provider", nil) + } + + site, err := common.GetSiteFromIDString(ctx, nil, machine.SiteID.String(), b.dbSession) + if err != nil { + if errors.Is(err, cdb.ErrDoesNotExist) || errors.Is(err, common.ErrInvalidID) { + return nil, "", nil, cutil.NewAPIErrorResponse(c, http.StatusBadRequest, "Machine Site does not exist", nil) + } + logger.Error().Err(err).Msg("error retrieving Machine Site from DB") + return nil, "", nil, cutil.NewAPIErrorResponse(c, http.StatusInternalServerError, "Failed to retrieve Machine Site due to DB error", nil) + } + if site.InfrastructureProviderID != provider.ID { + return nil, "", nil, cutil.NewAPIErrorResponse(c, http.StatusForbidden, "Machine Site doesn't belong to current org's Provider", nil) + } + + stc, err := b.scp.GetClientByID(site.ID) + if err != nil { + logger.Error().Err(err).Msg("failed to retrieve Temporal client for Site") + return nil, "", nil, cutil.NewAPIErrorResponse(c, http.StatusInternalServerError, "Failed to retrieve client for Site", nil) + } + return stc, site.ID.String(), machine, nil +} diff --git a/rest-api/api/pkg/api/handler/adminops_test.go b/rest-api/api/pkg/api/handler/adminops_test.go new file mode 100644 index 0000000000..25d6f7cd1b --- /dev/null +++ b/rest-api/api/pkg/api/handler/adminops_test.go @@ -0,0 +1,204 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package handler + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/labstack/echo/v4" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + tmocks "go.temporal.io/sdk/mocks" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" + + "github.com/NVIDIA/infra-controller/rest-api/api/pkg/api/handler/util/common" + "github.com/NVIDIA/infra-controller/rest-api/api/pkg/api/model" + sc "github.com/NVIDIA/infra-controller/rest-api/api/pkg/client/site" + authz "github.com/NVIDIA/infra-controller/rest-api/auth/pkg/authorization" + "github.com/NVIDIA/infra-controller/rest-api/common/pkg/coreproxy" + cutil "github.com/NVIDIA/infra-controller/rest-api/common/pkg/util" + cdbm "github.com/NVIDIA/infra-controller/rest-api/db/pkg/db/model" + cwssaws "github.com/NVIDIA/infra-controller/rest-api/workflow-schema/schema/site-agent/workflows/v1" +) + +type adminOpsHandlerFixture struct { + org string + siteID string + machineID string + user interface{} + handler echo.HandlerFunc + proxiedReq *coreproxy.Request +} + +func newAdminOpsHandlerFixture(t *testing.T, handlerName string, response proto.Message) adminOpsHandlerFixture { + t.Helper() + + dbSession := common.TestInitDB(t) + t.Cleanup(dbSession.Close) + common.TestSetupSchema(t, dbSession) + + org := "test-org" + user := common.TestBuildUser(t, dbSession, "test-starfleet-id", org, []string{authz.ProviderAdminRole}) + ip := common.TestBuildInfrastructureProvider(t, dbSession, "Test Infrastructure Provider", org, user) + site := common.TestBuildSite(t, dbSession, ip, "Test Site", user) + it := common.TestBuildInstanceType(t, dbSession, "test-instance-type", cutil.GetPtr(site.ID), site, nil, user) + machine := common.TestBuildMachine(t, dbSession, ip, site, &it.ID, cutil.GetPtr("test-controller-machine-type"), cdbm.MachineStatusReady) + + proxiedReq := &coreproxy.Request{} + wrun := &tmocks.WorkflowRun{} + wrun.On("Get", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + if response == nil { + return + } + out := args.Get(1).(*coreproxy.Response) + respJSON, err := protojson.Marshal(response) + require.NoError(t, err) + out.ResponseJSON = respJSON + }).Return(nil) + + tsc := &tmocks.Client{} + tsc.On( + "ExecuteWorkflow", + mock.Anything, + mock.Anything, + coreproxy.WorkflowName, + mock.MatchedBy(func(req coreproxy.Request) bool { + *proxiedReq = req + return true + }), + ).Return(wrun, nil) + + scp := sc.NewClientPool(nil) + scp.IDClientMap[site.ID.String()] = tsc + + cfg := common.GetTestConfig() + var handler echo.HandlerFunc + switch handlerName { + case "health-list": + h := NewListMachineHealthReportHandler(dbSession, scp, cfg) + handler = h.Handle + case "health-insert": + h := NewInsertMachineHealthReportHandler(dbSession, scp, cfg) + handler = h.Handle + case "health-remove": + h := NewRemoveMachineHealthReportHandler(dbSession, scp, cfg) + handler = h.Handle + default: + t.Fatalf("unknown handler %q", handlerName) + } + + return adminOpsHandlerFixture{ + org: org, + siteID: site.ID.String(), + machineID: machine.ID, + user: user, + handler: handler, + proxiedReq: proxiedReq, + } +} + +func (f adminOpsHandlerFixture) request(t *testing.T, method, target string, body any, source string) *httptest.ResponseRecorder { + t.Helper() + + var reqBody string + if body != nil { + bodyBytes, err := json.Marshal(body) + require.NoError(t, err) + reqBody = string(bodyBytes) + } + + e := echo.New() + req := httptest.NewRequest(method, target, strings.NewReader(reqBody)) + if body != nil { + req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) + } + rec := httptest.NewRecorder() + ec := e.NewContext(req, rec) + names := []string{"orgName", "machineId"} + values := []string{f.org, f.machineID} + if source != "" { + names = append(names, "source") + values = append(values, source) + } + ec.SetParamNames(names...) + ec.SetParamValues(values...) + ec.Set("user", f.user) + + require.NoError(t, f.handler(ec)) + return rec +} + +func TestListMachineHealthReportHandlerProxiesRequest(t *testing.T) { + fixture := newAdminOpsHandlerFixture(t, "health-list", &cwssaws.ListHealthReportResponse{ + HealthReportEntries: []*cwssaws.HealthReportEntry{ + { + Mode: cwssaws.HealthReportApplyMode_Merge, + Report: &cwssaws.HealthReport{ + Source: "overrides.sre", + Alerts: []*cwssaws.HealthProbeAlert{{Id: "probe.alert", Message: "forced unhealthy"}}, + }, + }, + }, + }) + + rec := fixture.request(t, http.MethodGet, "/", nil, "") + assert.Equal(t, http.StatusOK, rec.Code) + assert.Equal(t, cwssaws.Forge_ListMachineHealthReports_FullMethodName, fixture.proxiedReq.FullMethod) + assert.Empty(t, fixture.proxiedReq.EncryptedSecrets) + + var coreReq cwssaws.MachineId + require.NoError(t, protojson.Unmarshal(fixture.proxiedReq.RequestJSON, &coreReq)) + assert.Equal(t, fixture.machineID, coreReq.GetId()) + assert.Contains(t, rec.Body.String(), "overrides.sre") + assert.NotContains(t, rec.Body.String(), "password") +} + +func TestInsertMachineHealthReportHandlerProxiesRequest(t *testing.T) { + fixture := newAdminOpsHandlerFixture(t, "health-insert", nil) + req := model.APIMachineHealthReportEntry{ + Source: "overrides.sre", + Mode: model.MachineHealthReportModeMerge, + Alerts: []model.APIMachineHealthProbeAlert{{ID: "probe.alert", Message: "forced unhealthy"}}, + } + + rec := fixture.request(t, http.MethodPut, "/", req, "") + assert.Equal(t, http.StatusOK, rec.Code) + assert.Equal(t, cwssaws.Forge_InsertMachineHealthReport_FullMethodName, fixture.proxiedReq.FullMethod) + assert.Empty(t, fixture.proxiedReq.EncryptedSecrets) + + var coreReq cwssaws.InsertMachineHealthReportRequest + require.NoError(t, protojson.Unmarshal(fixture.proxiedReq.RequestJSON, &coreReq)) + assert.Equal(t, fixture.machineID, coreReq.GetMachineId().GetId()) + assert.Equal(t, "overrides.sre", coreReq.GetHealthReportEntry().GetReport().GetSource()) + assert.NotContains(t, rec.Body.String(), "password") +} + +func TestInsertMachineHealthReportHandlerRejectsInvalidRequest(t *testing.T) { + fixture := newAdminOpsHandlerFixture(t, "health-insert", nil) + + rec := fixture.request(t, http.MethodPut, "/", model.APIMachineHealthReportEntry{Mode: model.MachineHealthReportModeMerge}, "") + assert.Equal(t, http.StatusBadRequest, rec.Code) + assert.Empty(t, fixture.proxiedReq.FullMethod) +} + +func TestRemoveMachineHealthReportHandlerProxiesRequest(t *testing.T) { + fixture := newAdminOpsHandlerFixture(t, "health-remove", nil) + + rec := fixture.request(t, http.MethodDelete, "/", nil, "overrides.sre") + assert.Equal(t, http.StatusOK, rec.Code) + assert.Equal(t, cwssaws.Forge_RemoveMachineHealthReport_FullMethodName, fixture.proxiedReq.FullMethod) + assert.Empty(t, fixture.proxiedReq.EncryptedSecrets) + + var coreReq cwssaws.RemoveMachineHealthReportRequest + require.NoError(t, protojson.Unmarshal(fixture.proxiedReq.RequestJSON, &coreReq)) + assert.Equal(t, fixture.machineID, coreReq.GetMachineId().GetId()) + assert.Equal(t, "overrides.sre", coreReq.GetSource()) + assert.NotContains(t, rec.Body.String(), "password") +} diff --git a/rest-api/api/pkg/api/handler/healthoverride.go b/rest-api/api/pkg/api/handler/healthoverride.go new file mode 100644 index 0000000000..efdecedee7 --- /dev/null +++ b/rest-api/api/pkg/api/handler/healthoverride.go @@ -0,0 +1,163 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package handler + +import ( + "net/http" + + "github.com/labstack/echo/v4" + + "github.com/NVIDIA/infra-controller/rest-api/api/internal/config" + "github.com/NVIDIA/infra-controller/rest-api/api/pkg/api/handler/util/common" + "github.com/NVIDIA/infra-controller/rest-api/api/pkg/api/model" + sc "github.com/NVIDIA/infra-controller/rest-api/api/pkg/client/site" + cutil "github.com/NVIDIA/infra-controller/rest-api/common/pkg/util" + cdb "github.com/NVIDIA/infra-controller/rest-api/db/pkg/db" + cwssaws "github.com/NVIDIA/infra-controller/rest-api/workflow-schema/schema/site-agent/workflows/v1" +) + +type ListMachineHealthReportHandler struct { + adminMachineBase +} + +func NewListMachineHealthReportHandler(dbSession *cdb.Session, scp *sc.ClientPool, cfg *config.Config) ListMachineHealthReportHandler { + return ListMachineHealthReportHandler{ + adminMachineBase{dbSession: dbSession, scp: scp, cfg: cfg, tracerSpan: cutil.NewTracerSpan()}, + } +} + +// Handle godoc +// @Summary List Machine Health Reports +// @Description List Machine health report overrides through NICo Core. Provider Admin only. +// @Tags health-report +// @Accept json +// @Produce json +// @Security ApiKeyAuth +// @Param org path string true "Name of NGC organization" +// @Param machineId path string true "ID of Machine" +// @Success 200 {object} model.APIMachineHealthReportListResponse +// @Router /v2/org/{org}/nico/machine/{machineId}/health-report [get] +func (h ListMachineHealthReportHandler) Handle(c echo.Context) error { + org, dbUser, ctx, logger, handlerSpan := common.SetupHandler("MachineHealthReport", "List", c, h.tracerSpan) + if handlerSpan != nil { + defer handlerSpan.End() + } + + machineID := c.Param("machineId") + stc, siteID, _, errResp := h.authorizeMachine(ctx, c, logger, org, dbUser, machineID) + if errResp != nil || stc == nil { + return errResp + } + + logger.Info().Str("machineID", machineID).Str("siteID", siteID).Msg("listing Machine health reports via Core proxy") + coreResp := &cwssaws.ListHealthReportResponse{} + code, err := common.ExecuteCoreGRPC(ctx, stc, cwssaws.Forge_ListMachineHealthReports_FullMethodName, model.NewMachineIDProto(machineID), coreResp, siteID) + if err != nil { + logger.Error().Err(err).Msg("failed to list Machine health reports") + return cutil.NewAPIErrorResponse(c, code, "Failed to list Machine health reports", nil) + } + + return c.JSON(http.StatusOK, model.NewAPIMachineHealthReportListResponse(machineID, coreResp)) +} + +type InsertMachineHealthReportHandler struct { + adminMachineBase +} + +func NewInsertMachineHealthReportHandler(dbSession *cdb.Session, scp *sc.ClientPool, cfg *config.Config) InsertMachineHealthReportHandler { + return InsertMachineHealthReportHandler{ + adminMachineBase{dbSession: dbSession, scp: scp, cfg: cfg, tracerSpan: cutil.NewTracerSpan()}, + } +} + +// Handle godoc +// @Summary Insert Machine Health Report +// @Description Add or update a Machine health report override through NICo Core. Provider Admin only. +// @Tags health-report +// @Accept json +// @Produce json +// @Security ApiKeyAuth +// @Param org path string true "Name of NGC organization" +// @Param machineId path string true "ID of Machine" +// @Param request body model.APIMachineHealthReportEntry true "Machine health report" +// @Success 200 {object} model.APIMachineHealthReportResponse +// @Router /v2/org/{org}/nico/machine/{machineId}/health-report [put] +func (h InsertMachineHealthReportHandler) Handle(c echo.Context) error { + org, dbUser, ctx, logger, handlerSpan := common.SetupHandler("MachineHealthReport", "Insert", c, h.tracerSpan) + if handlerSpan != nil { + defer handlerSpan.End() + } + + machineID := c.Param("machineId") + var apiReq model.APIMachineHealthReportEntry + if err := c.Bind(&apiReq); err != nil { + return cutil.NewAPIErrorResponse(c, http.StatusBadRequest, "Invalid request body", nil) + } + if err := apiReq.Validate(); err != nil { + return cutil.NewAPIErrorResponse(c, http.StatusBadRequest, err.Error(), nil) + } + + stc, siteID, _, errResp := h.authorizeMachine(ctx, c, logger, org, dbUser, machineID) + if errResp != nil || stc == nil { + return errResp + } + + logger.Info().Str("machineID", machineID).Str("source", apiReq.Source).Str("siteID", siteID).Msg("inserting Machine health report via Core proxy") + code, err := common.ExecuteCoreGRPC(ctx, stc, cwssaws.Forge_InsertMachineHealthReport_FullMethodName, apiReq.ToProto(machineID), nil, siteID) + if err != nil { + logger.Error().Err(err).Msg("failed to insert Machine health report") + return cutil.NewAPIErrorResponse(c, code, "Failed to insert Machine health report", nil) + } + + return c.JSON(http.StatusOK, model.NewAPIMachineHealthReportResponse(machineID, &apiReq)) +} + +type RemoveMachineHealthReportHandler struct { + adminMachineBase +} + +func NewRemoveMachineHealthReportHandler(dbSession *cdb.Session, scp *sc.ClientPool, cfg *config.Config) RemoveMachineHealthReportHandler { + return RemoveMachineHealthReportHandler{ + adminMachineBase{dbSession: dbSession, scp: scp, cfg: cfg, tracerSpan: cutil.NewTracerSpan()}, + } +} + +// Handle godoc +// @Summary Remove Machine Health Report +// @Description Remove a Machine health report override through NICo Core. Provider Admin only. +// @Tags health-report +// @Accept json +// @Produce json +// @Security ApiKeyAuth +// @Param org path string true "Name of NGC organization" +// @Param machineId path string true "ID of Machine" +// @Param source path string true "Health report source" +// @Success 200 {object} model.APIMachineHealthReportRemoveResponse +// @Router /v2/org/{org}/nico/machine/{machineId}/health-report/{source} [delete] +func (h RemoveMachineHealthReportHandler) Handle(c echo.Context) error { + org, dbUser, ctx, logger, handlerSpan := common.SetupHandler("MachineHealthReport", "Remove", c, h.tracerSpan) + if handlerSpan != nil { + defer handlerSpan.End() + } + + machineID := c.Param("machineId") + source := c.Param("source") + if source == "" { + return cutil.NewAPIErrorResponse(c, http.StatusBadRequest, "source is required", nil) + } + + stc, siteID, _, errResp := h.authorizeMachine(ctx, c, logger, org, dbUser, machineID) + if errResp != nil || stc == nil { + return errResp + } + + logger.Info().Str("machineID", machineID).Str("source", source).Str("siteID", siteID).Msg("removing Machine health report via Core proxy") + code, err := common.ExecuteCoreGRPC(ctx, stc, cwssaws.Forge_RemoveMachineHealthReport_FullMethodName, model.NewRemoveMachineHealthReportProto(machineID, source), nil, siteID) + if err != nil { + logger.Error().Err(err).Msg("failed to remove Machine health report") + return cutil.NewAPIErrorResponse(c, code, "Failed to remove Machine health report", nil) + } + + return c.JSON(http.StatusOK, model.NewAPIMachineHealthReportRemoveResponse(machineID, source)) +} diff --git a/rest-api/api/pkg/api/model/adminops_test.go b/rest-api/api/pkg/api/model/adminops_test.go new file mode 100644 index 0000000000..d9e1e20ffb --- /dev/null +++ b/rest-api/api/pkg/api/model/adminops_test.go @@ -0,0 +1,85 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package model + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + cwssaws "github.com/NVIDIA/infra-controller/rest-api/workflow-schema/schema/site-agent/workflows/v1" +) + +func adminOpsStrPtr(s string) *string { return &s } + +func TestAPIMachineHealthReportEntryValidateAndToProto(t *testing.T) { + observedAt := "2026-06-24T12:00:00Z" + inAlertSince := "2026-06-24T11:00:00Z" + req := APIMachineHealthReportEntry{ + Source: "overrides.sre", + TriggeredBy: adminOpsStrPtr("operator"), + ObservedAt: &observedAt, + Mode: MachineHealthReportModeReplace, + Successes: []APIMachineHealthProbeSuccess{ + {ID: "probe.ok", Target: adminOpsStrPtr("host")}, + }, + Alerts: []APIMachineHealthProbeAlert{ + { + ID: "probe.alert", + Target: adminOpsStrPtr("gpu0"), + InAlertSince: &inAlertSince, + Message: "forced unhealthy", + TenantMessage: adminOpsStrPtr("maintenance"), + Classifications: []string{"maintenance"}, + }, + }, + } + require.NoError(t, req.Validate()) + + protoReq := req.ToProto("machine-1") + assert.Equal(t, "machine-1", protoReq.GetMachineId().GetId()) + entry := protoReq.GetHealthReportEntry() + require.NotNil(t, entry) + assert.Equal(t, cwssaws.HealthReportApplyMode_Replace, entry.GetMode()) + report := entry.GetReport() + require.NotNil(t, report) + assert.Equal(t, "overrides.sre", report.GetSource()) + assert.Equal(t, "operator", report.GetTriggeredBy()) + assert.Equal(t, observedAt, report.GetObservedAt().AsTime().Format("2006-01-02T15:04:05Z07:00")) + require.Len(t, report.GetSuccesses(), 1) + assert.Equal(t, "probe.ok", report.GetSuccesses()[0].GetId()) + require.Len(t, report.GetAlerts(), 1) + assert.Equal(t, "probe.alert", report.GetAlerts()[0].GetId()) + assert.Equal(t, inAlertSince, report.GetAlerts()[0].GetInAlertSince().AsTime().Format("2006-01-02T15:04:05Z07:00")) + + assert.Error(t, (&APIMachineHealthReportEntry{Mode: MachineHealthReportModeMerge}).Validate()) + assert.Error(t, (&APIMachineHealthReportEntry{Source: "source", Mode: "merge"}).Validate()) + assert.Error(t, (&APIMachineHealthReportEntry{Source: "source", Mode: MachineHealthReportModeMerge, ObservedAt: adminOpsStrPtr("bad-time")}).Validate()) + assert.Error(t, (&APIMachineHealthReportEntry{Source: "source", Mode: MachineHealthReportModeMerge, Alerts: []APIMachineHealthProbeAlert{{ID: "alert"}}}).Validate()) +} + +func TestAPIMachineHealthReportListResponseFromProto(t *testing.T) { + resp := NewAPIMachineHealthReportListResponse("machine-1", &cwssaws.ListHealthReportResponse{ + HealthReportEntries: []*cwssaws.HealthReportEntry{ + { + Mode: cwssaws.HealthReportApplyMode_Merge, + Report: &cwssaws.HealthReport{ + Source: "overrides.sre", + Alerts: []*cwssaws.HealthProbeAlert{{Id: "probe.alert", Message: "forced unhealthy"}}, + }, + }, + }, + }) + + assert.Equal(t, "machine-1", resp.MachineID) + require.Len(t, resp.HealthReportEntries, 1) + assert.Equal(t, MachineHealthReportModeMerge, resp.HealthReportEntries[0].Mode) + assert.Equal(t, "overrides.sre", resp.HealthReportEntries[0].Source) + + body, err := json.Marshal(resp) + require.NoError(t, err) + assert.NotContains(t, string(body), "password") +} diff --git a/rest-api/api/pkg/api/model/healthoverride.go b/rest-api/api/pkg/api/model/healthoverride.go new file mode 100644 index 0000000000..52cba174f4 --- /dev/null +++ b/rest-api/api/pkg/api/model/healthoverride.go @@ -0,0 +1,258 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package model + +import ( + "fmt" + "time" + + cwssaws "github.com/NVIDIA/infra-controller/rest-api/workflow-schema/schema/site-agent/workflows/v1" + validation "github.com/go-ozzo/ozzo-validation/v4" + "google.golang.org/protobuf/types/known/timestamppb" +) + +const ( + MachineHealthReportModeMerge = "Merge" + MachineHealthReportModeReplace = "Replace" +) + +var validMachineHealthReportModes = []string{ + MachineHealthReportModeMerge, + MachineHealthReportModeReplace, +} + +var validMachineHealthReportModesAny = func() []interface{} { + result := make([]interface{}, len(validMachineHealthReportModes)) + for i, mode := range validMachineHealthReportModes { + result[i] = mode + } + return result +}() + +type APIMachineHealthReportEntry struct { + Source string `json:"source"` + TriggeredBy *string `json:"triggeredBy,omitempty"` + ObservedAt *string `json:"observedAt,omitempty"` + Successes []APIMachineHealthProbeSuccess `json:"successes,omitempty"` + Alerts []APIMachineHealthProbeAlert `json:"alerts,omitempty"` + Mode string `json:"mode"` +} + +func (r *APIMachineHealthReportEntry) Validate() error { + if err := validation.ValidateStruct(r, + validation.Field(&r.Source, validation.Required.Error(validationErrorValueRequired)), + validation.Field(&r.Mode, + validation.Required.Error(validationErrorValueRequired), + validation.In(validMachineHealthReportModesAny...).Error(fmt.Sprintf("must be one of %v", validMachineHealthReportModes))), + ); err != nil { + return err + } + if err := validateOptionalRFC3339(r.ObservedAt, "observedAt"); err != nil { + return err + } + for i := range r.Successes { + if err := validation.ValidateStruct(&r.Successes[i], + validation.Field(&r.Successes[i].ID, validation.Required.Error(validationErrorValueRequired)), + ); err != nil { + return fmt.Errorf("successes[%d]: %w", i, err) + } + } + for i := range r.Alerts { + if err := validateOptionalRFC3339(r.Alerts[i].InAlertSince, fmt.Sprintf("alerts[%d].inAlertSince", i)); err != nil { + return err + } + if err := validation.ValidateStruct(&r.Alerts[i], + validation.Field(&r.Alerts[i].ID, validation.Required.Error(validationErrorValueRequired)), + validation.Field(&r.Alerts[i].Message, validation.Required.Error(validationErrorValueRequired)), + ); err != nil { + return fmt.Errorf("alerts[%d]: %w", i, err) + } + } + return nil +} + +func (r *APIMachineHealthReportEntry) ToProto(machineID string) *cwssaws.InsertMachineHealthReportRequest { + return &cwssaws.InsertMachineHealthReportRequest{ + MachineId: &cwssaws.MachineId{Id: machineID}, + HealthReportEntry: &cwssaws.HealthReportEntry{ + Report: &cwssaws.HealthReport{ + Source: r.Source, + TriggeredBy: r.TriggeredBy, + ObservedAt: stringToProtoTime(r.ObservedAt), + Successes: successesToProto(r.Successes), + Alerts: alertsToProto(r.Alerts), + }, + Mode: healthReportModeToProto(r.Mode), + }, + } +} + +type APIMachineHealthReportListResponse struct { + MachineID string `json:"machineId"` + HealthReportEntries []APIMachineHealthReportEntry `json:"healthReportEntries"` +} + +func NewAPIMachineHealthReportListResponse(machineID string, resp *cwssaws.ListHealthReportResponse) *APIMachineHealthReportListResponse { + entries := []APIMachineHealthReportEntry{} + if resp != nil { + entries = make([]APIMachineHealthReportEntry, 0, len(resp.GetHealthReportEntries())) + for _, entry := range resp.GetHealthReportEntries() { + entries = append(entries, machineHealthReportEntryFromProto(entry)) + } + } + return &APIMachineHealthReportListResponse{ + MachineID: machineID, + HealthReportEntries: entries, + } +} + +type APIMachineHealthReportResponse struct { + MachineID string `json:"machineId"` + HealthReportEntry APIMachineHealthReportEntry `json:"healthReportEntry"` +} + +func NewAPIMachineHealthReportResponse(machineID string, req *APIMachineHealthReportEntry) *APIMachineHealthReportResponse { + return &APIMachineHealthReportResponse{ + MachineID: machineID, + HealthReportEntry: *req, + } +} + +type APIMachineHealthReportRemoveResponse struct { + MachineID string `json:"machineId"` + Source string `json:"source"` +} + +func NewAPIMachineHealthReportRemoveResponse(machineID, source string) *APIMachineHealthReportRemoveResponse { + return &APIMachineHealthReportRemoveResponse{ + MachineID: machineID, + Source: source, + } +} + +func NewMachineIDProto(machineID string) *cwssaws.MachineId { + return &cwssaws.MachineId{Id: machineID} +} + +func NewRemoveMachineHealthReportProto(machineID, source string) *cwssaws.RemoveMachineHealthReportRequest { + return &cwssaws.RemoveMachineHealthReportRequest{ + MachineId: NewMachineIDProto(machineID), + Source: source, + } +} + +func healthReportModeToProto(mode string) cwssaws.HealthReportApplyMode { + switch mode { + case MachineHealthReportModeReplace: + return cwssaws.HealthReportApplyMode_Replace + default: + return cwssaws.HealthReportApplyMode_Merge + } +} + +func machineHealthReportModeFromProto(mode cwssaws.HealthReportApplyMode) string { + switch mode { + case cwssaws.HealthReportApplyMode_Replace: + return MachineHealthReportModeReplace + default: + return MachineHealthReportModeMerge + } +} + +func successesToProto(successes []APIMachineHealthProbeSuccess) []*cwssaws.HealthProbeSuccess { + out := make([]*cwssaws.HealthProbeSuccess, 0, len(successes)) + for _, success := range successes { + out = append(out, &cwssaws.HealthProbeSuccess{ + Id: success.ID, + Target: success.Target, + }) + } + return out +} + +func alertsToProto(alerts []APIMachineHealthProbeAlert) []*cwssaws.HealthProbeAlert { + out := make([]*cwssaws.HealthProbeAlert, 0, len(alerts)) + for _, alert := range alerts { + out = append(out, &cwssaws.HealthProbeAlert{ + Id: alert.ID, + Target: alert.Target, + InAlertSince: stringToProtoTime(alert.InAlertSince), + Message: alert.Message, + TenantMessage: alert.TenantMessage, + Classifications: alert.Classifications, + }) + } + return out +} + +func machineHealthReportEntryFromProto(entry *cwssaws.HealthReportEntry) APIMachineHealthReportEntry { + apiEntry := APIMachineHealthReportEntry{ + Mode: machineHealthReportModeFromProto(entry.GetMode()), + } + report := entry.GetReport() + if report == nil { + return apiEntry + } + apiEntry.Source = report.GetSource() + apiEntry.TriggeredBy = report.TriggeredBy + apiEntry.ObservedAt = stringFromProtoTime(report.GetObservedAt()) + apiEntry.Successes = successesFromProto(report.GetSuccesses()) + apiEntry.Alerts = alertsFromProto(report.GetAlerts()) + return apiEntry +} + +func successesFromProto(successes []*cwssaws.HealthProbeSuccess) []APIMachineHealthProbeSuccess { + out := make([]APIMachineHealthProbeSuccess, 0, len(successes)) + for _, success := range successes { + out = append(out, APIMachineHealthProbeSuccess{ + ID: success.GetId(), + Target: success.Target, + }) + } + return out +} + +func alertsFromProto(alerts []*cwssaws.HealthProbeAlert) []APIMachineHealthProbeAlert { + out := make([]APIMachineHealthProbeAlert, 0, len(alerts)) + for _, alert := range alerts { + out = append(out, APIMachineHealthProbeAlert{ + ID: alert.GetId(), + Target: alert.Target, + InAlertSince: stringFromProtoTime(alert.GetInAlertSince()), + Message: alert.GetMessage(), + TenantMessage: alert.TenantMessage, + Classifications: alert.GetClassifications(), + }) + } + return out +} + +func validateOptionalRFC3339(value *string, field string) error { + if value == nil || *value == "" { + return nil + } + if _, err := time.Parse(time.RFC3339Nano, *value); err != nil { + return fmt.Errorf("%s must be RFC3339 timestamp: %w", field, err) + } + return nil +} + +func stringToProtoTime(value *string) *timestamppb.Timestamp { + if value == nil || *value == "" { + return nil + } + t, err := time.Parse(time.RFC3339Nano, *value) + if err != nil { + return nil + } + return timestamppb.New(t) +} + +func stringFromProtoTime(t *timestamppb.Timestamp) *string { + if t == nil { + return nil + } + out := t.AsTime().Format(time.RFC3339Nano) + return &out +} diff --git a/rest-api/api/pkg/api/routes.go b/rest-api/api/pkg/api/routes.go index 4b69aefd74..08c550334a 100644 --- a/rest-api/api/pkg/api/routes.go +++ b/rest-api/api/pkg/api/routes.go @@ -546,6 +546,21 @@ func NewAPIRoutes(dbSession *cdb.Session, tc tClient.Client, tnc tClient.Namespa Method: http.MethodGet, Handler: apiHandler.NewGetMachineHandler(dbSession, tc, cfg), }, + { + Path: apiPathPrefix + "/machine/:machineId/health-report", + Method: http.MethodGet, + Handler: apiHandler.NewListMachineHealthReportHandler(dbSession, scp, cfg), + }, + { + Path: apiPathPrefix + "/machine/:machineId/health-report", + Method: http.MethodPut, + Handler: apiHandler.NewInsertMachineHealthReportHandler(dbSession, scp, cfg), + }, + { + Path: apiPathPrefix + "/machine/:machineId/health-report/:source", + Method: http.MethodDelete, + Handler: apiHandler.NewRemoveMachineHealthReportHandler(dbSession, scp, cfg), + }, { Path: apiPathPrefix + "/machine/:id", Method: http.MethodPatch, diff --git a/rest-api/api/pkg/api/routes_test.go b/rest-api/api/pkg/api/routes_test.go index 50ceca7614..24814b5e88 100644 --- a/rest-api/api/pkg/api/routes_test.go +++ b/rest-api/api/pkg/api/routes_test.go @@ -56,7 +56,7 @@ func TestNewAPIRoutes(t *testing.T) { "expected-rack": 7, "expected-switch": 5, "instance-type": 5, - "machine": 6, + "machine": 9, "allocation": 6, "subnet": 5, "machine-instance-type": 3, @@ -112,6 +112,11 @@ func TestNewAPIRoutes(t *testing.T) { bmcCredentialPath := "/org/:orgName/" + cfg.GetAPIName() + "/credential/bmc" assertRouteExists(t, got, http.MethodPut, bmcCredentialPath) + machineAdminPath := "/org/:orgName/" + cfg.GetAPIName() + "/machine/:machineId" + assertRouteExists(t, got, http.MethodGet, machineAdminPath+"/health-report") + assertRouteExists(t, got, http.MethodPut, machineAdminPath+"/health-report") + assertRouteExists(t, got, http.MethodDelete, machineAdminPath+"/health-report/:source") + expectedMachineBatchPath := "/org/:orgName/" + cfg.GetAPIName() + "/expected-machine/batch" assertRouteExists(t, got, http.MethodPost, expectedMachineBatchPath) assertRouteExists(t, got, http.MethodPatch, expectedMachineBatchPath) diff --git a/rest-api/openapi/spec.yaml b/rest-api/openapi/spec.yaml index 327eea4265..1971fb8e75 100644 --- a/rest-api/openapi/spec.yaml +++ b/rest-api/openapi/spec.yaml @@ -9123,6 +9123,117 @@ paths: description: Describes an error response for 500 Internal Server Error $ref: '#/components/responses/GenericHttpError' description: Org must have an Infrastructure Provider entity. Machine must belong to the Provider. User must have authorization role with `PROVIDER_ADMIN` suffix. Machine must meet certain criteria to be eligible for deletion. + '/v2/org/{org}/nico/machine/{machineId}/health-report': + parameters: + - schema: + type: string + name: org + in: path + required: true + description: Name of the Org + - schema: + type: string + name: machineId + in: path + required: true + description: ID of the Machine + get: + summary: List Machine health reports + tags: + - Health Report + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/MachineHealthReportListResponse' + '403': + $ref: '#/components/responses/ForbiddenError' + '404': + $ref: '#/components/responses/NotFoundError' + '500': + $ref: '#/components/responses/GenericHttpError' + operationId: list-machine-health-reports + description: |- + List Machine health report overrides through NICo Core. The request is + authorized, machine-scoped, and proxied to the Machine's owning Site. + User must have authorization role with `PROVIDER_ADMIN` suffix. + put: + summary: Insert Machine health report + tags: + - Health Report + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/MachineHealthReportEntry' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/MachineHealthReportResponse' + '400': + $ref: '#/components/responses/ValidationError' + '403': + $ref: '#/components/responses/ForbiddenError' + '404': + $ref: '#/components/responses/NotFoundError' + '500': + $ref: '#/components/responses/GenericHttpError' + operationId: insert-machine-health-report + description: |- + Add or update a Machine health report override through NICo Core. The + request is authorized, machine-scoped, and proxied to the Machine's + owning Site. User must have authorization role with `PROVIDER_ADMIN` + suffix. + '/v2/org/{org}/nico/machine/{machineId}/health-report/{source}': + parameters: + - schema: + type: string + name: org + in: path + required: true + description: Name of the Org + - schema: + type: string + name: machineId + in: path + required: true + description: ID of the Machine + - schema: + type: string + name: source + in: path + required: true + description: Health report source + delete: + summary: Remove Machine health report + tags: + - Health Report + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/MachineHealthReportRemoveResponse' + '400': + $ref: '#/components/responses/ValidationError' + '403': + $ref: '#/components/responses/ForbiddenError' + '404': + $ref: '#/components/responses/NotFoundError' + '500': + $ref: '#/components/responses/GenericHttpError' + operationId: remove-machine-health-report + description: |- + Remove a Machine health report override through NICo Core. The request + is authorized, machine-scoped, and proxied to the Machine's owning Site. + User must have authorization role with `PROVIDER_ADMIN` suffix. '/v2/org/{org}/nico/machine/{machineId}/status-history': parameters: - schema: @@ -13150,6 +13261,124 @@ components: macAddress: type: string description: BMC MAC address. Required for kind BMCRoot, ignored for SiteWideRoot. + MachineHealthReportEntry: + type: object + title: MachineHealthReportEntry + description: Machine health report entry submitted to NICo Core. + required: + - source + - mode + properties: + source: + type: string + description: Health report source. + triggeredBy: + type: string + description: Person or system that triggered this health report. + observedAt: + type: string + format: date-time + description: Date/time when the health report was observed. + successes: + type: array + items: + $ref: '#/components/schemas/MachineHealthReportProbeSuccess' + description: Results from successful health probes for the Machine. + alerts: + type: array + items: + $ref: '#/components/schemas/MachineHealthReportProbeAlert' + description: Results from failed health probes for the Machine. + mode: + type: string + description: How NICo Core applies this health report. + enum: + - Merge + - Replace + MachineHealthReportProbeSuccess: + type: object + title: MachineHealthReportProbeSuccess + description: Successful Machine health probe submitted to NICo Core. + required: + - id + properties: + id: + type: string + description: Health probe identifier. + target: + type: string + description: Specific component targeted by health probe. + MachineHealthReportProbeAlert: + type: object + title: MachineHealthReportProbeAlert + description: Failed Machine health probe submitted to NICo Core. + required: + - id + - message + properties: + id: + type: string + description: Health probe identifier. + target: + type: string + description: Specific component targeted by health probe. + inAlertSince: + type: string + format: date-time + description: Date/time since the alert has been in effect. + message: + type: string + description: Details of the failed health probe result. + tenantMessage: + type: string + description: Information provided by Tenant, if any. + classifications: + type: array + items: + type: string + description: Classifications for this alert. + MachineHealthReportListResponse: + type: object + title: MachineHealthReportListResponse + description: Machine health report entries returned by NICo Core. + required: + - machineId + - healthReportEntries + properties: + machineId: + type: string + description: ID of the Machine. + healthReportEntries: + type: array + items: + $ref: '#/components/schemas/MachineHealthReportEntry' + MachineHealthReportResponse: + type: object + title: MachineHealthReportResponse + description: Response for an inserted Machine health report. + required: + - machineId + - healthReportEntry + properties: + machineId: + type: string + description: ID of the Machine. + healthReportEntry: + $ref: '#/components/schemas/MachineHealthReportEntry' + MachineHealthReportRemoveResponse: + type: object + title: MachineHealthReportRemoveResponse + description: Response for a removed Machine health report. + required: + - machineId + - source + properties: + machineId: + type: string + description: ID of the Machine. + source: + type: string + description: Removed health report source. InfrastructureProvider: description: Infrastructure providers own and manage datacenters type: object diff --git a/rest-api/sdk/standard/api_health_report.go b/rest-api/sdk/standard/api_health_report.go new file mode 100644 index 0000000000..9f05704fb9 --- /dev/null +++ b/rest-api/sdk/standard/api_health_report.go @@ -0,0 +1,487 @@ +/* +NVIDIA Infra Controller REST API + +NVIDIA Infra Controller REST API allows users to create and manage resources, e.g., VPCs, Subnets, and Instances, across all connected NVIDIA Infra Controller datacenters, also referred to as Sites. + +API version: 1.6.0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package standard + +import ( + "bytes" + "context" + "io" + "net/http" + "net/url" + "strings" +) + +// HealthReportAPIService HealthReportAPI service +type HealthReportAPIService service + +type ApiInsertMachineHealthReportRequest struct { + ctx context.Context + ApiService *HealthReportAPIService + org string + machineId string + machineHealthReportEntry *MachineHealthReportEntry +} + +func (r ApiInsertMachineHealthReportRequest) MachineHealthReportEntry(machineHealthReportEntry MachineHealthReportEntry) ApiInsertMachineHealthReportRequest { + r.machineHealthReportEntry = &machineHealthReportEntry + return r +} + +func (r ApiInsertMachineHealthReportRequest) Execute() (*MachineHealthReportResponse, *http.Response, error) { + return r.ApiService.InsertMachineHealthReportExecute(r) +} + +/* +InsertMachineHealthReport Insert Machine health report + +Add or update a Machine health report override through NICo Core. The +request is authorized, machine-scoped, and proxied to the Machine's +owning Site. User must have authorization role with `PROVIDER_ADMIN` +suffix. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param org Name of the Org + @param machineId ID of the Machine + @return ApiInsertMachineHealthReportRequest +*/ +func (a *HealthReportAPIService) InsertMachineHealthReport(ctx context.Context, org string, machineId string) ApiInsertMachineHealthReportRequest { + return ApiInsertMachineHealthReportRequest{ + ApiService: a, + ctx: ctx, + org: org, + machineId: machineId, + } +} + +// Execute executes the request +// +// @return MachineHealthReportResponse +func (a *HealthReportAPIService) InsertMachineHealthReportExecute(r ApiInsertMachineHealthReportRequest) (*MachineHealthReportResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPut + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *MachineHealthReportResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "HealthReportAPIService.InsertMachineHealthReport") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/v2/org/{org}/nico/machine/{machineId}/health-report" + localVarPath = strings.Replace(localVarPath, "{"+"org"+"}", url.PathEscape(parameterValueToString(r.org, "org")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"machineId"+"}", url.PathEscape(parameterValueToString(r.machineId, "machineId")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.machineHealthReportEntry == nil { + return localVarReturnValue, nil, reportError("machineHealthReportEntry is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.machineHealthReportEntry + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v NICoAPIError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v NICoAPIError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NICoAPIError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v NICoAPIError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiListMachineHealthReportsRequest struct { + ctx context.Context + ApiService *HealthReportAPIService + org string + machineId string +} + +func (r ApiListMachineHealthReportsRequest) Execute() (*MachineHealthReportListResponse, *http.Response, error) { + return r.ApiService.ListMachineHealthReportsExecute(r) +} + +/* +ListMachineHealthReports List Machine health reports + +List Machine health report overrides through NICo Core. The request is +authorized, machine-scoped, and proxied to the Machine's owning Site. +User must have authorization role with `PROVIDER_ADMIN` suffix. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param org Name of the Org + @param machineId ID of the Machine + @return ApiListMachineHealthReportsRequest +*/ +func (a *HealthReportAPIService) ListMachineHealthReports(ctx context.Context, org string, machineId string) ApiListMachineHealthReportsRequest { + return ApiListMachineHealthReportsRequest{ + ApiService: a, + ctx: ctx, + org: org, + machineId: machineId, + } +} + +// Execute executes the request +// +// @return MachineHealthReportListResponse +func (a *HealthReportAPIService) ListMachineHealthReportsExecute(r ApiListMachineHealthReportsRequest) (*MachineHealthReportListResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *MachineHealthReportListResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "HealthReportAPIService.ListMachineHealthReports") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/v2/org/{org}/nico/machine/{machineId}/health-report" + localVarPath = strings.Replace(localVarPath, "{"+"org"+"}", url.PathEscape(parameterValueToString(r.org, "org")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"machineId"+"}", url.PathEscape(parameterValueToString(r.machineId, "machineId")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 403 { + var v NICoAPIError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NICoAPIError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v NICoAPIError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiRemoveMachineHealthReportRequest struct { + ctx context.Context + ApiService *HealthReportAPIService + org string + machineId string + source string +} + +func (r ApiRemoveMachineHealthReportRequest) Execute() (*MachineHealthReportRemoveResponse, *http.Response, error) { + return r.ApiService.RemoveMachineHealthReportExecute(r) +} + +/* +RemoveMachineHealthReport Remove Machine health report + +Remove a Machine health report override through NICo Core. The request +is authorized, machine-scoped, and proxied to the Machine's owning Site. +User must have authorization role with `PROVIDER_ADMIN` suffix. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param org Name of the Org + @param machineId ID of the Machine + @param source Health report source + @return ApiRemoveMachineHealthReportRequest +*/ +func (a *HealthReportAPIService) RemoveMachineHealthReport(ctx context.Context, org string, machineId string, source string) ApiRemoveMachineHealthReportRequest { + return ApiRemoveMachineHealthReportRequest{ + ApiService: a, + ctx: ctx, + org: org, + machineId: machineId, + source: source, + } +} + +// Execute executes the request +// +// @return MachineHealthReportRemoveResponse +func (a *HealthReportAPIService) RemoveMachineHealthReportExecute(r ApiRemoveMachineHealthReportRequest) (*MachineHealthReportRemoveResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *MachineHealthReportRemoveResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "HealthReportAPIService.RemoveMachineHealthReport") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/v2/org/{org}/nico/machine/{machineId}/health-report/{source}" + localVarPath = strings.Replace(localVarPath, "{"+"org"+"}", url.PathEscape(parameterValueToString(r.org, "org")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"machineId"+"}", url.PathEscape(parameterValueToString(r.machineId, "machineId")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"source"+"}", url.PathEscape(parameterValueToString(r.source, "source")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v NICoAPIError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v NICoAPIError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NICoAPIError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v NICoAPIError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/rest-api/sdk/standard/client.go b/rest-api/sdk/standard/client.go index 30b573f2ab..5fefdd40aa 100644 --- a/rest-api/sdk/standard/client.go +++ b/rest-api/sdk/standard/client.go @@ -67,6 +67,8 @@ type APIClient struct { ExpectedSwitchAPI *ExpectedSwitchAPIService + HealthReportAPI *HealthReportAPIService + IPBlockAPI *IPBlockAPIService InfiniBandPartitionAPI *InfiniBandPartitionAPIService @@ -146,6 +148,7 @@ func NewAPIClient(cfg *Configuration) *APIClient { c.ExpectedPowerShelfAPI = (*ExpectedPowerShelfAPIService)(&c.common) c.ExpectedRackAPI = (*ExpectedRackAPIService)(&c.common) c.ExpectedSwitchAPI = (*ExpectedSwitchAPIService)(&c.common) + c.HealthReportAPI = (*HealthReportAPIService)(&c.common) c.IPBlockAPI = (*IPBlockAPIService)(&c.common) c.InfiniBandPartitionAPI = (*InfiniBandPartitionAPIService)(&c.common) c.InfrastructureProviderAPI = (*InfrastructureProviderAPIService)(&c.common) diff --git a/rest-api/sdk/standard/model_machine_health_report_entry.go b/rest-api/sdk/standard/model_machine_health_report_entry.go new file mode 100644 index 0000000000..6a193f7a93 --- /dev/null +++ b/rest-api/sdk/standard/model_machine_health_report_entry.go @@ -0,0 +1,335 @@ +/* +NVIDIA Infra Controller REST API + +NVIDIA Infra Controller REST API allows users to create and manage resources, e.g., VPCs, Subnets, and Instances, across all connected NVIDIA Infra Controller datacenters, also referred to as Sites. + +API version: 1.6.0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package standard + +import ( + "bytes" + "encoding/json" + "fmt" + "time" +) + +// checks if the MachineHealthReportEntry type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &MachineHealthReportEntry{} + +// MachineHealthReportEntry Machine health report entry submitted to NICo Core. +type MachineHealthReportEntry struct { + // Health report source. + Source string `json:"source"` + // Person or system that triggered this health report. + TriggeredBy *string `json:"triggeredBy,omitempty"` + // Date/time when the health report was observed. + ObservedAt *time.Time `json:"observedAt,omitempty"` + // Results from successful health probes for the Machine. + Successes []MachineHealthReportProbeSuccess `json:"successes,omitempty"` + // Results from failed health probes for the Machine. + Alerts []MachineHealthReportProbeAlert `json:"alerts,omitempty"` + // How NICo Core applies this health report. + Mode string `json:"mode"` +} + +type _MachineHealthReportEntry MachineHealthReportEntry + +// NewMachineHealthReportEntry instantiates a new MachineHealthReportEntry object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMachineHealthReportEntry(source string, mode string) *MachineHealthReportEntry { + this := MachineHealthReportEntry{} + this.Source = source + this.Mode = mode + return &this +} + +// NewMachineHealthReportEntryWithDefaults instantiates a new MachineHealthReportEntry object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMachineHealthReportEntryWithDefaults() *MachineHealthReportEntry { + this := MachineHealthReportEntry{} + return &this +} + +// GetSource returns the Source field value +func (o *MachineHealthReportEntry) GetSource() string { + if o == nil { + var ret string + return ret + } + + return o.Source +} + +// GetSourceOk returns a tuple with the Source field value +// and a boolean to check if the value has been set. +func (o *MachineHealthReportEntry) GetSourceOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Source, true +} + +// SetSource sets field value +func (o *MachineHealthReportEntry) SetSource(v string) { + o.Source = v +} + +// GetTriggeredBy returns the TriggeredBy field value if set, zero value otherwise. +func (o *MachineHealthReportEntry) GetTriggeredBy() string { + if o == nil || IsNil(o.TriggeredBy) { + var ret string + return ret + } + return *o.TriggeredBy +} + +// GetTriggeredByOk returns a tuple with the TriggeredBy field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MachineHealthReportEntry) GetTriggeredByOk() (*string, bool) { + if o == nil || IsNil(o.TriggeredBy) { + return nil, false + } + return o.TriggeredBy, true +} + +// HasTriggeredBy returns a boolean if a field has been set. +func (o *MachineHealthReportEntry) HasTriggeredBy() bool { + if o != nil && !IsNil(o.TriggeredBy) { + return true + } + + return false +} + +// SetTriggeredBy gets a reference to the given string and assigns it to the TriggeredBy field. +func (o *MachineHealthReportEntry) SetTriggeredBy(v string) { + o.TriggeredBy = &v +} + +// GetObservedAt returns the ObservedAt field value if set, zero value otherwise. +func (o *MachineHealthReportEntry) GetObservedAt() time.Time { + if o == nil || IsNil(o.ObservedAt) { + var ret time.Time + return ret + } + return *o.ObservedAt +} + +// GetObservedAtOk returns a tuple with the ObservedAt field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MachineHealthReportEntry) GetObservedAtOk() (*time.Time, bool) { + if o == nil || IsNil(o.ObservedAt) { + return nil, false + } + return o.ObservedAt, true +} + +// HasObservedAt returns a boolean if a field has been set. +func (o *MachineHealthReportEntry) HasObservedAt() bool { + if o != nil && !IsNil(o.ObservedAt) { + return true + } + + return false +} + +// SetObservedAt gets a reference to the given time.Time and assigns it to the ObservedAt field. +func (o *MachineHealthReportEntry) SetObservedAt(v time.Time) { + o.ObservedAt = &v +} + +// GetSuccesses returns the Successes field value if set, zero value otherwise. +func (o *MachineHealthReportEntry) GetSuccesses() []MachineHealthReportProbeSuccess { + if o == nil || IsNil(o.Successes) { + var ret []MachineHealthReportProbeSuccess + return ret + } + return o.Successes +} + +// GetSuccessesOk returns a tuple with the Successes field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MachineHealthReportEntry) GetSuccessesOk() ([]MachineHealthReportProbeSuccess, bool) { + if o == nil || IsNil(o.Successes) { + return nil, false + } + return o.Successes, true +} + +// HasSuccesses returns a boolean if a field has been set. +func (o *MachineHealthReportEntry) HasSuccesses() bool { + if o != nil && !IsNil(o.Successes) { + return true + } + + return false +} + +// SetSuccesses gets a reference to the given []MachineHealthReportProbeSuccess and assigns it to the Successes field. +func (o *MachineHealthReportEntry) SetSuccesses(v []MachineHealthReportProbeSuccess) { + o.Successes = v +} + +// GetAlerts returns the Alerts field value if set, zero value otherwise. +func (o *MachineHealthReportEntry) GetAlerts() []MachineHealthReportProbeAlert { + if o == nil || IsNil(o.Alerts) { + var ret []MachineHealthReportProbeAlert + return ret + } + return o.Alerts +} + +// GetAlertsOk returns a tuple with the Alerts field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MachineHealthReportEntry) GetAlertsOk() ([]MachineHealthReportProbeAlert, bool) { + if o == nil || IsNil(o.Alerts) { + return nil, false + } + return o.Alerts, true +} + +// HasAlerts returns a boolean if a field has been set. +func (o *MachineHealthReportEntry) HasAlerts() bool { + if o != nil && !IsNil(o.Alerts) { + return true + } + + return false +} + +// SetAlerts gets a reference to the given []MachineHealthReportProbeAlert and assigns it to the Alerts field. +func (o *MachineHealthReportEntry) SetAlerts(v []MachineHealthReportProbeAlert) { + o.Alerts = v +} + +// GetMode returns the Mode field value +func (o *MachineHealthReportEntry) GetMode() string { + if o == nil { + var ret string + return ret + } + + return o.Mode +} + +// GetModeOk returns a tuple with the Mode field value +// and a boolean to check if the value has been set. +func (o *MachineHealthReportEntry) GetModeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Mode, true +} + +// SetMode sets field value +func (o *MachineHealthReportEntry) SetMode(v string) { + o.Mode = v +} + +func (o MachineHealthReportEntry) MarshalJSON() ([]byte, error) { + toSerialize, err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o MachineHealthReportEntry) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + toSerialize["source"] = o.Source + if !IsNil(o.TriggeredBy) { + toSerialize["triggeredBy"] = o.TriggeredBy + } + if !IsNil(o.ObservedAt) { + toSerialize["observedAt"] = o.ObservedAt + } + if !IsNil(o.Successes) { + toSerialize["successes"] = o.Successes + } + if !IsNil(o.Alerts) { + toSerialize["alerts"] = o.Alerts + } + toSerialize["mode"] = o.Mode + return toSerialize, nil +} + +func (o *MachineHealthReportEntry) UnmarshalJSON(data []byte) (err error) { + // This validates that all required properties are included in the JSON object + // by unmarshalling the object into a generic map with string keys and checking + // that every required field exists as a key in the generic map. + requiredProperties := []string{ + "source", + "mode", + } + + allProperties := make(map[string]interface{}) + + err = json.Unmarshal(data, &allProperties) + + if err != nil { + return err + } + + for _, requiredProperty := range requiredProperties { + if _, exists := allProperties[requiredProperty]; !exists { + return fmt.Errorf("no value given for required property %v", requiredProperty) + } + } + + varMachineHealthReportEntry := _MachineHealthReportEntry{} + + decoder := json.NewDecoder(bytes.NewReader(data)) + decoder.DisallowUnknownFields() + err = decoder.Decode(&varMachineHealthReportEntry) + + if err != nil { + return err + } + + *o = MachineHealthReportEntry(varMachineHealthReportEntry) + + return err +} + +type NullableMachineHealthReportEntry struct { + value *MachineHealthReportEntry + isSet bool +} + +func (v NullableMachineHealthReportEntry) Get() *MachineHealthReportEntry { + return v.value +} + +func (v *NullableMachineHealthReportEntry) Set(val *MachineHealthReportEntry) { + v.value = val + v.isSet = true +} + +func (v NullableMachineHealthReportEntry) IsSet() bool { + return v.isSet +} + +func (v *NullableMachineHealthReportEntry) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMachineHealthReportEntry(val *MachineHealthReportEntry) *NullableMachineHealthReportEntry { + return &NullableMachineHealthReportEntry{value: val, isSet: true} +} + +func (v NullableMachineHealthReportEntry) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMachineHealthReportEntry) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/rest-api/sdk/standard/model_machine_health_report_list_response.go b/rest-api/sdk/standard/model_machine_health_report_list_response.go new file mode 100644 index 0000000000..7228873bc6 --- /dev/null +++ b/rest-api/sdk/standard/model_machine_health_report_list_response.go @@ -0,0 +1,185 @@ +/* +NVIDIA Infra Controller REST API + +NVIDIA Infra Controller REST API allows users to create and manage resources, e.g., VPCs, Subnets, and Instances, across all connected NVIDIA Infra Controller datacenters, also referred to as Sites. + +API version: 1.6.0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package standard + +import ( + "bytes" + "encoding/json" + "fmt" +) + +// checks if the MachineHealthReportListResponse type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &MachineHealthReportListResponse{} + +// MachineHealthReportListResponse Machine health report entries returned by NICo Core. +type MachineHealthReportListResponse struct { + // ID of the Machine. + MachineId string `json:"machineId"` + HealthReportEntries []MachineHealthReportEntry `json:"healthReportEntries"` +} + +type _MachineHealthReportListResponse MachineHealthReportListResponse + +// NewMachineHealthReportListResponse instantiates a new MachineHealthReportListResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMachineHealthReportListResponse(machineId string, healthReportEntries []MachineHealthReportEntry) *MachineHealthReportListResponse { + this := MachineHealthReportListResponse{} + this.MachineId = machineId + this.HealthReportEntries = healthReportEntries + return &this +} + +// NewMachineHealthReportListResponseWithDefaults instantiates a new MachineHealthReportListResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMachineHealthReportListResponseWithDefaults() *MachineHealthReportListResponse { + this := MachineHealthReportListResponse{} + return &this +} + +// GetMachineId returns the MachineId field value +func (o *MachineHealthReportListResponse) GetMachineId() string { + if o == nil { + var ret string + return ret + } + + return o.MachineId +} + +// GetMachineIdOk returns a tuple with the MachineId field value +// and a boolean to check if the value has been set. +func (o *MachineHealthReportListResponse) GetMachineIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.MachineId, true +} + +// SetMachineId sets field value +func (o *MachineHealthReportListResponse) SetMachineId(v string) { + o.MachineId = v +} + +// GetHealthReportEntries returns the HealthReportEntries field value +func (o *MachineHealthReportListResponse) GetHealthReportEntries() []MachineHealthReportEntry { + if o == nil { + var ret []MachineHealthReportEntry + return ret + } + + return o.HealthReportEntries +} + +// GetHealthReportEntriesOk returns a tuple with the HealthReportEntries field value +// and a boolean to check if the value has been set. +func (o *MachineHealthReportListResponse) GetHealthReportEntriesOk() ([]MachineHealthReportEntry, bool) { + if o == nil { + return nil, false + } + return o.HealthReportEntries, true +} + +// SetHealthReportEntries sets field value +func (o *MachineHealthReportListResponse) SetHealthReportEntries(v []MachineHealthReportEntry) { + o.HealthReportEntries = v +} + +func (o MachineHealthReportListResponse) MarshalJSON() ([]byte, error) { + toSerialize, err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o MachineHealthReportListResponse) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + toSerialize["machineId"] = o.MachineId + toSerialize["healthReportEntries"] = o.HealthReportEntries + return toSerialize, nil +} + +func (o *MachineHealthReportListResponse) UnmarshalJSON(data []byte) (err error) { + // This validates that all required properties are included in the JSON object + // by unmarshalling the object into a generic map with string keys and checking + // that every required field exists as a key in the generic map. + requiredProperties := []string{ + "machineId", + "healthReportEntries", + } + + allProperties := make(map[string]interface{}) + + err = json.Unmarshal(data, &allProperties) + + if err != nil { + return err + } + + for _, requiredProperty := range requiredProperties { + if _, exists := allProperties[requiredProperty]; !exists { + return fmt.Errorf("no value given for required property %v", requiredProperty) + } + } + + varMachineHealthReportListResponse := _MachineHealthReportListResponse{} + + decoder := json.NewDecoder(bytes.NewReader(data)) + decoder.DisallowUnknownFields() + err = decoder.Decode(&varMachineHealthReportListResponse) + + if err != nil { + return err + } + + *o = MachineHealthReportListResponse(varMachineHealthReportListResponse) + + return err +} + +type NullableMachineHealthReportListResponse struct { + value *MachineHealthReportListResponse + isSet bool +} + +func (v NullableMachineHealthReportListResponse) Get() *MachineHealthReportListResponse { + return v.value +} + +func (v *NullableMachineHealthReportListResponse) Set(val *MachineHealthReportListResponse) { + v.value = val + v.isSet = true +} + +func (v NullableMachineHealthReportListResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableMachineHealthReportListResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMachineHealthReportListResponse(val *MachineHealthReportListResponse) *NullableMachineHealthReportListResponse { + return &NullableMachineHealthReportListResponse{value: val, isSet: true} +} + +func (v NullableMachineHealthReportListResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMachineHealthReportListResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/rest-api/sdk/standard/model_machine_health_report_probe_alert.go b/rest-api/sdk/standard/model_machine_health_report_probe_alert.go new file mode 100644 index 0000000000..b3f7778a68 --- /dev/null +++ b/rest-api/sdk/standard/model_machine_health_report_probe_alert.go @@ -0,0 +1,335 @@ +/* +NVIDIA Infra Controller REST API + +NVIDIA Infra Controller REST API allows users to create and manage resources, e.g., VPCs, Subnets, and Instances, across all connected NVIDIA Infra Controller datacenters, also referred to as Sites. + +API version: 1.6.0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package standard + +import ( + "bytes" + "encoding/json" + "fmt" + "time" +) + +// checks if the MachineHealthReportProbeAlert type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &MachineHealthReportProbeAlert{} + +// MachineHealthReportProbeAlert Failed Machine health probe submitted to NICo Core. +type MachineHealthReportProbeAlert struct { + // Health probe identifier. + Id string `json:"id"` + // Specific component targeted by health probe. + Target *string `json:"target,omitempty"` + // Date/time since the alert has been in effect. + InAlertSince *time.Time `json:"inAlertSince,omitempty"` + // Details of the failed health probe result. + Message string `json:"message"` + // Information provided by Tenant, if any. + TenantMessage *string `json:"tenantMessage,omitempty"` + // Classifications for this alert. + Classifications []string `json:"classifications,omitempty"` +} + +type _MachineHealthReportProbeAlert MachineHealthReportProbeAlert + +// NewMachineHealthReportProbeAlert instantiates a new MachineHealthReportProbeAlert object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMachineHealthReportProbeAlert(id string, message string) *MachineHealthReportProbeAlert { + this := MachineHealthReportProbeAlert{} + this.Id = id + this.Message = message + return &this +} + +// NewMachineHealthReportProbeAlertWithDefaults instantiates a new MachineHealthReportProbeAlert object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMachineHealthReportProbeAlertWithDefaults() *MachineHealthReportProbeAlert { + this := MachineHealthReportProbeAlert{} + return &this +} + +// GetId returns the Id field value +func (o *MachineHealthReportProbeAlert) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *MachineHealthReportProbeAlert) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *MachineHealthReportProbeAlert) SetId(v string) { + o.Id = v +} + +// GetTarget returns the Target field value if set, zero value otherwise. +func (o *MachineHealthReportProbeAlert) GetTarget() string { + if o == nil || IsNil(o.Target) { + var ret string + return ret + } + return *o.Target +} + +// GetTargetOk returns a tuple with the Target field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MachineHealthReportProbeAlert) GetTargetOk() (*string, bool) { + if o == nil || IsNil(o.Target) { + return nil, false + } + return o.Target, true +} + +// HasTarget returns a boolean if a field has been set. +func (o *MachineHealthReportProbeAlert) HasTarget() bool { + if o != nil && !IsNil(o.Target) { + return true + } + + return false +} + +// SetTarget gets a reference to the given string and assigns it to the Target field. +func (o *MachineHealthReportProbeAlert) SetTarget(v string) { + o.Target = &v +} + +// GetInAlertSince returns the InAlertSince field value if set, zero value otherwise. +func (o *MachineHealthReportProbeAlert) GetInAlertSince() time.Time { + if o == nil || IsNil(o.InAlertSince) { + var ret time.Time + return ret + } + return *o.InAlertSince +} + +// GetInAlertSinceOk returns a tuple with the InAlertSince field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MachineHealthReportProbeAlert) GetInAlertSinceOk() (*time.Time, bool) { + if o == nil || IsNil(o.InAlertSince) { + return nil, false + } + return o.InAlertSince, true +} + +// HasInAlertSince returns a boolean if a field has been set. +func (o *MachineHealthReportProbeAlert) HasInAlertSince() bool { + if o != nil && !IsNil(o.InAlertSince) { + return true + } + + return false +} + +// SetInAlertSince gets a reference to the given time.Time and assigns it to the InAlertSince field. +func (o *MachineHealthReportProbeAlert) SetInAlertSince(v time.Time) { + o.InAlertSince = &v +} + +// GetMessage returns the Message field value +func (o *MachineHealthReportProbeAlert) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *MachineHealthReportProbeAlert) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *MachineHealthReportProbeAlert) SetMessage(v string) { + o.Message = v +} + +// GetTenantMessage returns the TenantMessage field value if set, zero value otherwise. +func (o *MachineHealthReportProbeAlert) GetTenantMessage() string { + if o == nil || IsNil(o.TenantMessage) { + var ret string + return ret + } + return *o.TenantMessage +} + +// GetTenantMessageOk returns a tuple with the TenantMessage field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MachineHealthReportProbeAlert) GetTenantMessageOk() (*string, bool) { + if o == nil || IsNil(o.TenantMessage) { + return nil, false + } + return o.TenantMessage, true +} + +// HasTenantMessage returns a boolean if a field has been set. +func (o *MachineHealthReportProbeAlert) HasTenantMessage() bool { + if o != nil && !IsNil(o.TenantMessage) { + return true + } + + return false +} + +// SetTenantMessage gets a reference to the given string and assigns it to the TenantMessage field. +func (o *MachineHealthReportProbeAlert) SetTenantMessage(v string) { + o.TenantMessage = &v +} + +// GetClassifications returns the Classifications field value if set, zero value otherwise. +func (o *MachineHealthReportProbeAlert) GetClassifications() []string { + if o == nil || IsNil(o.Classifications) { + var ret []string + return ret + } + return o.Classifications +} + +// GetClassificationsOk returns a tuple with the Classifications field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MachineHealthReportProbeAlert) GetClassificationsOk() ([]string, bool) { + if o == nil || IsNil(o.Classifications) { + return nil, false + } + return o.Classifications, true +} + +// HasClassifications returns a boolean if a field has been set. +func (o *MachineHealthReportProbeAlert) HasClassifications() bool { + if o != nil && !IsNil(o.Classifications) { + return true + } + + return false +} + +// SetClassifications gets a reference to the given []string and assigns it to the Classifications field. +func (o *MachineHealthReportProbeAlert) SetClassifications(v []string) { + o.Classifications = v +} + +func (o MachineHealthReportProbeAlert) MarshalJSON() ([]byte, error) { + toSerialize, err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o MachineHealthReportProbeAlert) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + toSerialize["id"] = o.Id + if !IsNil(o.Target) { + toSerialize["target"] = o.Target + } + if !IsNil(o.InAlertSince) { + toSerialize["inAlertSince"] = o.InAlertSince + } + toSerialize["message"] = o.Message + if !IsNil(o.TenantMessage) { + toSerialize["tenantMessage"] = o.TenantMessage + } + if !IsNil(o.Classifications) { + toSerialize["classifications"] = o.Classifications + } + return toSerialize, nil +} + +func (o *MachineHealthReportProbeAlert) UnmarshalJSON(data []byte) (err error) { + // This validates that all required properties are included in the JSON object + // by unmarshalling the object into a generic map with string keys and checking + // that every required field exists as a key in the generic map. + requiredProperties := []string{ + "id", + "message", + } + + allProperties := make(map[string]interface{}) + + err = json.Unmarshal(data, &allProperties) + + if err != nil { + return err + } + + for _, requiredProperty := range requiredProperties { + if _, exists := allProperties[requiredProperty]; !exists { + return fmt.Errorf("no value given for required property %v", requiredProperty) + } + } + + varMachineHealthReportProbeAlert := _MachineHealthReportProbeAlert{} + + decoder := json.NewDecoder(bytes.NewReader(data)) + decoder.DisallowUnknownFields() + err = decoder.Decode(&varMachineHealthReportProbeAlert) + + if err != nil { + return err + } + + *o = MachineHealthReportProbeAlert(varMachineHealthReportProbeAlert) + + return err +} + +type NullableMachineHealthReportProbeAlert struct { + value *MachineHealthReportProbeAlert + isSet bool +} + +func (v NullableMachineHealthReportProbeAlert) Get() *MachineHealthReportProbeAlert { + return v.value +} + +func (v *NullableMachineHealthReportProbeAlert) Set(val *MachineHealthReportProbeAlert) { + v.value = val + v.isSet = true +} + +func (v NullableMachineHealthReportProbeAlert) IsSet() bool { + return v.isSet +} + +func (v *NullableMachineHealthReportProbeAlert) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMachineHealthReportProbeAlert(val *MachineHealthReportProbeAlert) *NullableMachineHealthReportProbeAlert { + return &NullableMachineHealthReportProbeAlert{value: val, isSet: true} +} + +func (v NullableMachineHealthReportProbeAlert) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMachineHealthReportProbeAlert) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/rest-api/sdk/standard/model_machine_health_report_probe_success.go b/rest-api/sdk/standard/model_machine_health_report_probe_success.go new file mode 100644 index 0000000000..8e9ef2f193 --- /dev/null +++ b/rest-api/sdk/standard/model_machine_health_report_probe_success.go @@ -0,0 +1,194 @@ +/* +NVIDIA Infra Controller REST API + +NVIDIA Infra Controller REST API allows users to create and manage resources, e.g., VPCs, Subnets, and Instances, across all connected NVIDIA Infra Controller datacenters, also referred to as Sites. + +API version: 1.6.0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package standard + +import ( + "bytes" + "encoding/json" + "fmt" +) + +// checks if the MachineHealthReportProbeSuccess type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &MachineHealthReportProbeSuccess{} + +// MachineHealthReportProbeSuccess Successful Machine health probe submitted to NICo Core. +type MachineHealthReportProbeSuccess struct { + // Health probe identifier. + Id string `json:"id"` + // Specific component targeted by health probe. + Target *string `json:"target,omitempty"` +} + +type _MachineHealthReportProbeSuccess MachineHealthReportProbeSuccess + +// NewMachineHealthReportProbeSuccess instantiates a new MachineHealthReportProbeSuccess object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMachineHealthReportProbeSuccess(id string) *MachineHealthReportProbeSuccess { + this := MachineHealthReportProbeSuccess{} + this.Id = id + return &this +} + +// NewMachineHealthReportProbeSuccessWithDefaults instantiates a new MachineHealthReportProbeSuccess object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMachineHealthReportProbeSuccessWithDefaults() *MachineHealthReportProbeSuccess { + this := MachineHealthReportProbeSuccess{} + return &this +} + +// GetId returns the Id field value +func (o *MachineHealthReportProbeSuccess) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *MachineHealthReportProbeSuccess) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *MachineHealthReportProbeSuccess) SetId(v string) { + o.Id = v +} + +// GetTarget returns the Target field value if set, zero value otherwise. +func (o *MachineHealthReportProbeSuccess) GetTarget() string { + if o == nil || IsNil(o.Target) { + var ret string + return ret + } + return *o.Target +} + +// GetTargetOk returns a tuple with the Target field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MachineHealthReportProbeSuccess) GetTargetOk() (*string, bool) { + if o == nil || IsNil(o.Target) { + return nil, false + } + return o.Target, true +} + +// HasTarget returns a boolean if a field has been set. +func (o *MachineHealthReportProbeSuccess) HasTarget() bool { + if o != nil && !IsNil(o.Target) { + return true + } + + return false +} + +// SetTarget gets a reference to the given string and assigns it to the Target field. +func (o *MachineHealthReportProbeSuccess) SetTarget(v string) { + o.Target = &v +} + +func (o MachineHealthReportProbeSuccess) MarshalJSON() ([]byte, error) { + toSerialize, err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o MachineHealthReportProbeSuccess) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + toSerialize["id"] = o.Id + if !IsNil(o.Target) { + toSerialize["target"] = o.Target + } + return toSerialize, nil +} + +func (o *MachineHealthReportProbeSuccess) UnmarshalJSON(data []byte) (err error) { + // This validates that all required properties are included in the JSON object + // by unmarshalling the object into a generic map with string keys and checking + // that every required field exists as a key in the generic map. + requiredProperties := []string{ + "id", + } + + allProperties := make(map[string]interface{}) + + err = json.Unmarshal(data, &allProperties) + + if err != nil { + return err + } + + for _, requiredProperty := range requiredProperties { + if _, exists := allProperties[requiredProperty]; !exists { + return fmt.Errorf("no value given for required property %v", requiredProperty) + } + } + + varMachineHealthReportProbeSuccess := _MachineHealthReportProbeSuccess{} + + decoder := json.NewDecoder(bytes.NewReader(data)) + decoder.DisallowUnknownFields() + err = decoder.Decode(&varMachineHealthReportProbeSuccess) + + if err != nil { + return err + } + + *o = MachineHealthReportProbeSuccess(varMachineHealthReportProbeSuccess) + + return err +} + +type NullableMachineHealthReportProbeSuccess struct { + value *MachineHealthReportProbeSuccess + isSet bool +} + +func (v NullableMachineHealthReportProbeSuccess) Get() *MachineHealthReportProbeSuccess { + return v.value +} + +func (v *NullableMachineHealthReportProbeSuccess) Set(val *MachineHealthReportProbeSuccess) { + v.value = val + v.isSet = true +} + +func (v NullableMachineHealthReportProbeSuccess) IsSet() bool { + return v.isSet +} + +func (v *NullableMachineHealthReportProbeSuccess) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMachineHealthReportProbeSuccess(val *MachineHealthReportProbeSuccess) *NullableMachineHealthReportProbeSuccess { + return &NullableMachineHealthReportProbeSuccess{value: val, isSet: true} +} + +func (v NullableMachineHealthReportProbeSuccess) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMachineHealthReportProbeSuccess) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/rest-api/sdk/standard/model_machine_health_report_remove_response.go b/rest-api/sdk/standard/model_machine_health_report_remove_response.go new file mode 100644 index 0000000000..e4dafe5753 --- /dev/null +++ b/rest-api/sdk/standard/model_machine_health_report_remove_response.go @@ -0,0 +1,186 @@ +/* +NVIDIA Infra Controller REST API + +NVIDIA Infra Controller REST API allows users to create and manage resources, e.g., VPCs, Subnets, and Instances, across all connected NVIDIA Infra Controller datacenters, also referred to as Sites. + +API version: 1.6.0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package standard + +import ( + "bytes" + "encoding/json" + "fmt" +) + +// checks if the MachineHealthReportRemoveResponse type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &MachineHealthReportRemoveResponse{} + +// MachineHealthReportRemoveResponse Response for a removed Machine health report. +type MachineHealthReportRemoveResponse struct { + // ID of the Machine. + MachineId string `json:"machineId"` + // Removed health report source. + Source string `json:"source"` +} + +type _MachineHealthReportRemoveResponse MachineHealthReportRemoveResponse + +// NewMachineHealthReportRemoveResponse instantiates a new MachineHealthReportRemoveResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMachineHealthReportRemoveResponse(machineId string, source string) *MachineHealthReportRemoveResponse { + this := MachineHealthReportRemoveResponse{} + this.MachineId = machineId + this.Source = source + return &this +} + +// NewMachineHealthReportRemoveResponseWithDefaults instantiates a new MachineHealthReportRemoveResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMachineHealthReportRemoveResponseWithDefaults() *MachineHealthReportRemoveResponse { + this := MachineHealthReportRemoveResponse{} + return &this +} + +// GetMachineId returns the MachineId field value +func (o *MachineHealthReportRemoveResponse) GetMachineId() string { + if o == nil { + var ret string + return ret + } + + return o.MachineId +} + +// GetMachineIdOk returns a tuple with the MachineId field value +// and a boolean to check if the value has been set. +func (o *MachineHealthReportRemoveResponse) GetMachineIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.MachineId, true +} + +// SetMachineId sets field value +func (o *MachineHealthReportRemoveResponse) SetMachineId(v string) { + o.MachineId = v +} + +// GetSource returns the Source field value +func (o *MachineHealthReportRemoveResponse) GetSource() string { + if o == nil { + var ret string + return ret + } + + return o.Source +} + +// GetSourceOk returns a tuple with the Source field value +// and a boolean to check if the value has been set. +func (o *MachineHealthReportRemoveResponse) GetSourceOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Source, true +} + +// SetSource sets field value +func (o *MachineHealthReportRemoveResponse) SetSource(v string) { + o.Source = v +} + +func (o MachineHealthReportRemoveResponse) MarshalJSON() ([]byte, error) { + toSerialize, err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o MachineHealthReportRemoveResponse) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + toSerialize["machineId"] = o.MachineId + toSerialize["source"] = o.Source + return toSerialize, nil +} + +func (o *MachineHealthReportRemoveResponse) UnmarshalJSON(data []byte) (err error) { + // This validates that all required properties are included in the JSON object + // by unmarshalling the object into a generic map with string keys and checking + // that every required field exists as a key in the generic map. + requiredProperties := []string{ + "machineId", + "source", + } + + allProperties := make(map[string]interface{}) + + err = json.Unmarshal(data, &allProperties) + + if err != nil { + return err + } + + for _, requiredProperty := range requiredProperties { + if _, exists := allProperties[requiredProperty]; !exists { + return fmt.Errorf("no value given for required property %v", requiredProperty) + } + } + + varMachineHealthReportRemoveResponse := _MachineHealthReportRemoveResponse{} + + decoder := json.NewDecoder(bytes.NewReader(data)) + decoder.DisallowUnknownFields() + err = decoder.Decode(&varMachineHealthReportRemoveResponse) + + if err != nil { + return err + } + + *o = MachineHealthReportRemoveResponse(varMachineHealthReportRemoveResponse) + + return err +} + +type NullableMachineHealthReportRemoveResponse struct { + value *MachineHealthReportRemoveResponse + isSet bool +} + +func (v NullableMachineHealthReportRemoveResponse) Get() *MachineHealthReportRemoveResponse { + return v.value +} + +func (v *NullableMachineHealthReportRemoveResponse) Set(val *MachineHealthReportRemoveResponse) { + v.value = val + v.isSet = true +} + +func (v NullableMachineHealthReportRemoveResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableMachineHealthReportRemoveResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMachineHealthReportRemoveResponse(val *MachineHealthReportRemoveResponse) *NullableMachineHealthReportRemoveResponse { + return &NullableMachineHealthReportRemoveResponse{value: val, isSet: true} +} + +func (v NullableMachineHealthReportRemoveResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMachineHealthReportRemoveResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/rest-api/sdk/standard/model_machine_health_report_response.go b/rest-api/sdk/standard/model_machine_health_report_response.go new file mode 100644 index 0000000000..fd66a5d9be --- /dev/null +++ b/rest-api/sdk/standard/model_machine_health_report_response.go @@ -0,0 +1,185 @@ +/* +NVIDIA Infra Controller REST API + +NVIDIA Infra Controller REST API allows users to create and manage resources, e.g., VPCs, Subnets, and Instances, across all connected NVIDIA Infra Controller datacenters, also referred to as Sites. + +API version: 1.6.0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package standard + +import ( + "bytes" + "encoding/json" + "fmt" +) + +// checks if the MachineHealthReportResponse type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &MachineHealthReportResponse{} + +// MachineHealthReportResponse Response for an inserted Machine health report. +type MachineHealthReportResponse struct { + // ID of the Machine. + MachineId string `json:"machineId"` + HealthReportEntry MachineHealthReportEntry `json:"healthReportEntry"` +} + +type _MachineHealthReportResponse MachineHealthReportResponse + +// NewMachineHealthReportResponse instantiates a new MachineHealthReportResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMachineHealthReportResponse(machineId string, healthReportEntry MachineHealthReportEntry) *MachineHealthReportResponse { + this := MachineHealthReportResponse{} + this.MachineId = machineId + this.HealthReportEntry = healthReportEntry + return &this +} + +// NewMachineHealthReportResponseWithDefaults instantiates a new MachineHealthReportResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMachineHealthReportResponseWithDefaults() *MachineHealthReportResponse { + this := MachineHealthReportResponse{} + return &this +} + +// GetMachineId returns the MachineId field value +func (o *MachineHealthReportResponse) GetMachineId() string { + if o == nil { + var ret string + return ret + } + + return o.MachineId +} + +// GetMachineIdOk returns a tuple with the MachineId field value +// and a boolean to check if the value has been set. +func (o *MachineHealthReportResponse) GetMachineIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.MachineId, true +} + +// SetMachineId sets field value +func (o *MachineHealthReportResponse) SetMachineId(v string) { + o.MachineId = v +} + +// GetHealthReportEntry returns the HealthReportEntry field value +func (o *MachineHealthReportResponse) GetHealthReportEntry() MachineHealthReportEntry { + if o == nil { + var ret MachineHealthReportEntry + return ret + } + + return o.HealthReportEntry +} + +// GetHealthReportEntryOk returns a tuple with the HealthReportEntry field value +// and a boolean to check if the value has been set. +func (o *MachineHealthReportResponse) GetHealthReportEntryOk() (*MachineHealthReportEntry, bool) { + if o == nil { + return nil, false + } + return &o.HealthReportEntry, true +} + +// SetHealthReportEntry sets field value +func (o *MachineHealthReportResponse) SetHealthReportEntry(v MachineHealthReportEntry) { + o.HealthReportEntry = v +} + +func (o MachineHealthReportResponse) MarshalJSON() ([]byte, error) { + toSerialize, err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o MachineHealthReportResponse) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + toSerialize["machineId"] = o.MachineId + toSerialize["healthReportEntry"] = o.HealthReportEntry + return toSerialize, nil +} + +func (o *MachineHealthReportResponse) UnmarshalJSON(data []byte) (err error) { + // This validates that all required properties are included in the JSON object + // by unmarshalling the object into a generic map with string keys and checking + // that every required field exists as a key in the generic map. + requiredProperties := []string{ + "machineId", + "healthReportEntry", + } + + allProperties := make(map[string]interface{}) + + err = json.Unmarshal(data, &allProperties) + + if err != nil { + return err + } + + for _, requiredProperty := range requiredProperties { + if _, exists := allProperties[requiredProperty]; !exists { + return fmt.Errorf("no value given for required property %v", requiredProperty) + } + } + + varMachineHealthReportResponse := _MachineHealthReportResponse{} + + decoder := json.NewDecoder(bytes.NewReader(data)) + decoder.DisallowUnknownFields() + err = decoder.Decode(&varMachineHealthReportResponse) + + if err != nil { + return err + } + + *o = MachineHealthReportResponse(varMachineHealthReportResponse) + + return err +} + +type NullableMachineHealthReportResponse struct { + value *MachineHealthReportResponse + isSet bool +} + +func (v NullableMachineHealthReportResponse) Get() *MachineHealthReportResponse { + return v.value +} + +func (v *NullableMachineHealthReportResponse) Set(val *MachineHealthReportResponse) { + v.value = val + v.isSet = true +} + +func (v NullableMachineHealthReportResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableMachineHealthReportResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMachineHealthReportResponse(val *MachineHealthReportResponse) *NullableMachineHealthReportResponse { + return &NullableMachineHealthReportResponse{value: val, isSet: true} +} + +func (v NullableMachineHealthReportResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMachineHealthReportResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +}