diff --git a/pkg/models/devices_api.go b/pkg/models/devices_api.go new file mode 100644 index 000000000..c8d44c6ed --- /dev/null +++ b/pkg/models/devices_api.go @@ -0,0 +1,81 @@ +package models + +// EdgeDeviceAPI is the entity that represents and Edge Device +// It is a combination of the data of a Device owned by Inventory API +// and the Device data saved on Edge API +type EdgeDeviceAPI struct { + *Device + DeviceName string `example:"device_name"` // The device name + LastSeen string `example:"2023-07-19T08:09:08.084004+00:00"` // Last datetime that device updated + Booted bool `example:"true"` // Booted status is referring to the LastDeployment of this device +} + +// DeviceGroupAPI is a record of Edge Devices Groups +// Account is the account associated with the device group +// Type is the device group type and must be "static" or "dynamic" +type DeviceGroupAPI struct { + Name string `json:"Name" example:"device_group name"` // The device group name` + Type string `json:"Type" example:"static"` // The device group type`` + Devices []Device `faker:"-" json:"Devices"` // Devices that belong to the group + ValidUpdate bool `json:"ValidUpdate" example:"true"` // indicate if the update is valid +} + +// UpdateTransactionAPI represents the combination of an OSTree commit and a set of Inventory +type UpdateTransactionAPI struct { + Model + Commit *Commit `json:"Commit"` + CommitID uint `json:"CommitID" example:"1754"` // Commit ID of device + OldCommits []Commit `json:"OldCommits"` // Old Commit ID if the device has one + Devices []Device `json:"Devices"` // List of Devices + Tag string `json:"Tag" example:"device_tag"` // Tag og Device if device has one + Status string `json:"Status" example:"SUCCESS"` // Status of device + RepoID *uint `json:"RepoID" example:"2256"` // Repo ID + Repo *Repo `json:"Repo"` + ChangesRefs bool `json:"ChangesRefs" example:"false"` + DispatchRecords []DispatchRecord `json:"DispatchRecords"` +} + +// DeviceDetailsAPI is a Device with Image and Update transactions +// It contains data from multiple tables on the database +type DeviceDetailsAPI struct { + Device EdgeDeviceAPI `json:"Device,omitempty"` // Details of device like name, LastSeen and more + Image *ImageInfo `json:"ImageInfo"` // Information of device's image + UpdateTransactions *[]UpdateTransactionAPI `json:"UpdateTransactions,omitempty"` + DevicesGroups *[]DeviceGroupAPI `json:"DevicesGroups,omitempty"` // Device's groups + Updating *bool `json:"DeviceUpdating,omitempty" example:"true"` // If there is update to device +} + +// DeviceDetailsListAPI is the list of devices with details from Inventory and Edge API +type DeviceDetailsListAPI struct { + Total int `json:"total" example:"40"` // total number of device + Count int `json:"count" example:"40"` // total number of device + Devices []DeviceDetailsAPI `json:"data"` // List of Devices +} + +// DeviceDeviceGroupAPI is a struct of device group name and id needed for DeviceView +type DeviceDeviceGroupAPI struct { + ID uint + Name string +} + +// DeviceViewAPI is the device information needed for the UI +type DeviceViewAPI struct { + DeviceID uint `json:"DeviceID" example:"1913277"` // ID of device + DeviceName string `json:"DeviceName" example:"device_name"` // Name of device + DeviceUUID string `json:"DeviceUUID"` + ImageID uint `json:"ImageID" example:"323241"` // ID of image + ImageName string `json:"ImageName" example:"image_name"` // Name of image + LastSeen EdgeAPITime `json:"LastSeen" example:"2023-07-19T08:09:08.084004+00:00"` // Last datetime that device updated` + UpdateAvailable bool `json:"UpdateAvailable" example:"true"` // indicate if there is update to device + Status string `json:"Status" example:"SUCCESS"` // Status of device + ImageSetID uint `json:"ImageSetID" example:"323234341"` // ID of image set + DeviceGroups []DeviceDeviceGroupAPI `json:"DeviceGroups"` // Device's groups + DispatcherStatus string `json:"DispatcherStatus"` + DispatcherReason string `json:"DispatcherReason"` +} + +// DeviceViewListAPI is the list of devices for a given account, formatted for the UI +type DeviceViewListAPI struct { + Total int64 `json:"total" example:"40"` // total number of device` + Devices []DeviceViewAPI `json:"devices"` // List of Devices +} diff --git a/pkg/routes/devices.go b/pkg/routes/devices.go index 92b96d159..9b4320781 100644 --- a/pkg/routes/devices.go +++ b/pkg/routes/devices.go @@ -147,17 +147,18 @@ func ValidateGetDevicesViewFilterParams(next http.Handler) http.Handler { } // GetUpdateAvailableForDevice returns if exists update for the current image at the device. -// @Summary Placeholder summary -// @Description This is a placeholder description +// @ID GetUpdateAvailableForDevice +// @Summary Return list of available updates for a device. +// @Description Return list of available updates for a device. // @Tags Devices (Systems) // @Accept json // @Produce json -// @Param required_parm query string true "A placeholder for required parameter" example(cat) -// @Param optional_parm query int false "A placeholder for optional parameter" example(42) -// @Success 200 {object} models.SuccessPlaceholderResponse -// @Failure 400 {object} errors.BadRequest -// @Failure 500 {object} errors.InternalServerError -// @Router /devices/{DeviceUUID}/updates [get] +// @Param DeviceUUID path string true "DeviceUUID" +// @Param latest query string false "query the latest or all updates" +// @Success 200 {object} models.Image +// @Failure 400 {object} errors.BadRequest "The request sent couldn't be processed." +// @Failure 500 {object} errors.InternalServerError "There was an internal server error." +// @Router /updates/device/{DeviceUUID}/updates [get] func GetUpdateAvailableForDevice(w http.ResponseWriter, r *http.Request) { contextServices := dependencies.ServicesFromContext(r.Context()) dc, ok := r.Context().Value(deviceContextKey).(DeviceContext) @@ -187,18 +188,7 @@ func GetUpdateAvailableForDevice(w http.ResponseWriter, r *http.Request) { respondWithJSONBody(w, contextServices.Log, result) } -// GetDeviceImageInfo returns the information of a running image for a device -// @Summary Placeholder summary -// @Description This is a placeholder description -// @Tags Devices (Systems) -// @Accept json -// @Produce json -// @Param required_parm query string true "A placeholder for required parameter" example(cat) -// @Param optional_parm query int false "A placeholder for optional parameter" example(42) -// @Success 200 {object} models.SuccessPlaceholderResponse -// @Failure 400 {object} errors.BadRequest -// @Failure 500 {object} errors.InternalServerError -// @Router /devices/{DeviceUUID}/image [get] +// GetDeviceImageInfo returns the information of a running image func GetDeviceImageInfo(w http.ResponseWriter, r *http.Request) { contextServices := dependencies.ServicesFromContext(r.Context()) dc, ok := r.Context().Value(deviceContextKey).(DeviceContext) @@ -226,17 +216,18 @@ func GetDeviceImageInfo(w http.ResponseWriter, r *http.Request) { // Returns the information of a running image and previous image in case of a rollback. // Returns updates available to a device. // Returns updates transactions for that device, if any. -// @Summary Placeholder summary -// @Description This is a placeholder description +// @ID GetDevice +// @Summary Get a device by UUID. +// @Description Get a device by UUID. // @Tags Devices (Systems) // @Accept json // @Produce json -// @Param required_parm query string true "A placeholder for required parameter" example(cat) -// @Param optional_parm query int false "A placeholder for optional parameter" example(42) -// @Success 200 {object} models.SuccessPlaceholderResponse -// @Failure 400 {object} errors.BadRequest -// @Failure 500 {object} errors.InternalServerError -// @Router /devices/{DeviceUUID}/ [get] +// @Param DeviceUUID path string true "DeviceUUID" +// @Success 200 {object} models.DeviceDetailsAPI +// @Failure 400 {object} errors.BadRequest "The request sent couldn't be processed." +// @Failure 404 {object} errors.NotFound "The device was not found." +// @Failure 500 {object} errors.InternalServerError "There was an internal server error." +// @Router /devices/{DeviceUUID} [get] func GetDevice(w http.ResponseWriter, r *http.Request) { contextServices := dependencies.ServicesFromContext(r.Context()) dc, ok := r.Context().Value(deviceContextKey).(DeviceContext) @@ -291,15 +282,19 @@ func deviceListFilters(v url.Values) *inventory.Params { } // GetDevices return the device data both on Edge API and InventoryAPI -// @Summary Get system data +// @ID GetDevices +// @Summary Get All Devices. // @Description Get combined system data from Edge API and Inventory API // @Tags Devices (Systems) // @Accept json // @Produce json -// @Param order_by query string false "Order by display_name, updated or operating_system" -// @Success 200 {object} models.DeviceDetailsList -// @Failure 400 {object} errors.BadRequest -// @Failure 500 {object} errors.InternalServerError +// @Param per_page query int false "field: maximum devices per page" +// @Param page query int false "field: which page to query from" +// @Param order_by query string false "field: order by display_name, updated or operating_system" +// @Param order_how query string false "field: choose to order ASC or DESC when order_by is being used" +// @Param hostname_or_id query string false "field: filter by hostname_or_id" +// @Success 200 {object} models.DeviceDetailsListAPI +// @Failure 500 {object} errors.InternalServerError "There was an internal server error." // @Router /devices [get] func GetDevices(w http.ResponseWriter, r *http.Request) { contextServices := dependencies.ServicesFromContext(r.Context()) @@ -313,17 +308,6 @@ func GetDevices(w http.ResponseWriter, r *http.Request) { } // GetDeviceDBInfo return the device data on EdgeAPI DB -// @Summary Placeholder summary -// @Description This is a placeholder description -// @Tags Devices (Systems) -// @Accept json -// @Produce json -// @Param required_parm query string true "A placeholder for required parameter" example(cat) -// @Param optional_parm query int false "A placeholder for optional parameter" example(42) -// @Success 200 {object} models.SuccessPlaceholderResponse -// @Failure 400 {object} errors.BadRequest -// @Failure 500 {object} errors.InternalServerError -// @Router /devices/{DeviceUUID}/dbinfo [get] func GetDeviceDBInfo(w http.ResponseWriter, r *http.Request) { contextServices := dependencies.ServicesFromContext(r.Context()) var devices []models.Device @@ -345,16 +329,22 @@ func GetDeviceDBInfo(w http.ResponseWriter, r *http.Request) { } // GetDevicesView returns all data needed to display customers devices -// @Summary Placeholder summary -// @Description This is a placeholder description +// @ID GetDevicesView +// @Summary Return all data of Devices. +// @Description Return all data of Devices. // @Tags Devices (Systems) // @Accept json // @Produce json -// @Param required_parm query string true "A placeholder for required parameter" example(cat) -// @Param optional_parm query int false "A placeholder for optional parameter" example(42) -// @Success 200 {object} models.SuccessPlaceholderResponse -// @Failure 400 {object} errors.BadRequest -// @Failure 500 {object} errors.InternalServerError +// @Param sort_by query string false "fields: name, uuid, update_available, image_id. To sort DESC use - before the fields." +// @Param name query string false "field: filter by name" +// @Param update_available query boolean false "field: filter by update_available" +// @Param uuid query string false "field: filter by uuid" +// @Param created_at query string false "field: filter by creation date" +// @Param image_id query int false "field: filter by image id" +// @Param limit query int false "field: return number of devices until limit is reached. Default is 100." +// @Param offset query int false "field: return number of devices begining at the offset." +// @Success 200 {object} models.DeviceViewListAPI +// @Failure 500 {object} errors.InternalServerError "There was an internal server error." // @Router /devices/devicesview [get] func GetDevicesView(w http.ResponseWriter, r *http.Request) { contextServices := dependencies.ServicesFromContext(r.Context()) diff --git a/pkg/routes/imagesets.go b/pkg/routes/imagesets.go index 0fd86f766..e002a962f 100644 --- a/pkg/routes/imagesets.go +++ b/pkg/routes/imagesets.go @@ -189,8 +189,8 @@ type ImageSetInstallerURL struct { // @Param sort_by query string false "Define sort fields: created_at, updated_at, name. To sort DESC use -" // @Param name query string false "field: filter by name" // @Param status query string false "field: filter by status" -// @Param limit query integer false "field: return number of image-set view until limit is reached. Default is 100." -// @Param offset query integer false "field: return number of image-set view beginning at the offset." +// @Param limit query int false "field: return number of image-set view until limit is reached. Default is 100." +// @Param offset query int false "field: return number of image-set view beginning at the offset." // @Success 200 {object} models.ImageSetsResponseAPI // @Failure 400 {object} errors.BadRequest "The request sent couldn't be processed." // @Failure 404 {object} errors.NotFound "The Image Set was not found." @@ -301,13 +301,13 @@ type ImageSetImagePackages struct { // @Tags Image-Sets // @Accept json // @Produce json -// @Param imageSetID path integer true "Image Set ID" +// @Param imageSetID path int true "Image Set ID" // @Param sort_by query string false "Define sort fields: created_at, updated_at, name. To sort DESC use -" // @Param name query string false "field: filter by name" // @Param status query string false "field: filter by status" // @Param version query string false "field: filter by version" -// @Param limit query integer false "field: return number of image-set view until limit is reached. Default is 100." -// @Param offset query integer false "field: return number of image-set view beginning at the offset." +// @Param limit query int false "field: return number of image-set view until limit is reached. Default is 100." +// @Param offset query int false "field: return number of image-set view beginning at the offset." // @Success 200 {object} models.ImageSetDetailsResponseAPI // @Failure 400 {object} errors.BadRequest "The request sent couldn't be processed." // @Failure 404 {object} errors.NotFound "image-set was not found." @@ -519,9 +519,9 @@ func returnImageDetails(images []models.Image, s *dependencies.EdgeAPIServices) // @Param sort_by query string false "Define sort fields: created_at, updated_at, name. To sort DESC use -" // @Param name query string false "field: filter by name" // @Param status query string false "field: filter by status" -// @Param id query integer false "field: filter by id" -// @Param limit query integer false "field: return number of image-set view until limit is reached. Default is 30." -// @Param offset query integer false "field: return number of image-set view beginning at the offset." +// @Param id query int false "field: filter by id" +// @Param limit query int false "field: return number of image-set view until limit is reached. Default is 30." +// @Param offset query int false "field: return number of image-set view beginning at the offset." // @Success 200 {object} models.ImageSetsViewResponseAPI // @Failure 500 {object} errors.InternalServerError "There was an internal server error." // @Router /image-sets/view [get] @@ -605,7 +605,7 @@ func getContextImageSet(w http.ResponseWriter, r *http.Request) *models.ImageSet // @Tags Image-Sets // @Accept json // @Produce json -// @Param image_set_id path integer true "the image-set id" +// @Param image_set_id path int true "the image-set id" // @Success 200 {object} models.ImageSetIDViewAPI // @Failure 400 {object} errors.BadRequest "The request sent couldn't be processed." // @Failure 404 {object} errors.NotFound "The Image-Set was not found." @@ -649,8 +649,8 @@ func GetImageSetViewByID(w http.ResponseWriter, r *http.Request) { // @Param sort_by query string false "Define sort fields: created_at, version, To sort DESC use -" // @Param status query string false "field: filter by status" // @Param version query string false "field: filter by version" -// @Param limit query integer false "field: return number of images until limit is reached. Default is 100." -// @Param offset query integer false "field: return number of images beginning at the offset." +// @Param limit query int false "field: return number of images until limit is reached. Default is 100." +// @Param offset query int false "field: return number of images beginning at the offset." // @Success 200 {object} models.ImagesViewDataAPI // @Failure 400 {object} errors.BadRequest "The request sent couldn't be processed." // @Failure 404 {object} errors.NotFound "The Image-Set was not found."