Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions hawkbit/lib_software_module_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package hawkbit
const (
softwareModuleNameParam = "name"
softwareModuleVersionParam = "version"
softwareModuleStoredPath = "path"
)

// SoftwareModuleID represents an unique identifier for software modules.
Expand All @@ -24,4 +25,6 @@ type SoftwareModuleID struct {
Name string `json:"name"`
// Version of the software module.
Version string `json:"version"`
// Stored downloaded file path
Path string `json:"path,omitempty"`
}
35 changes: 18 additions & 17 deletions hawkbit/lib_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,22 @@ type Status string

// Supported operation statuses.
const (
StatusStarted Status = "STARTED"
StatusDownloading Status = "DOWNLOADING"
StatusDownloadingWaiting Status = "DOWNLOADING_WAITING"
StatusDownloaded Status = "DOWNLOADED"
StatusInstalling Status = "INSTALLING"
StatusInstallingWaiting Status = "INSTALLING_WAITING"
StatusInstalled Status = "INSTALLED"
StatusRemoving Status = "REMOVING"
StatusRemovingWaiting Status = "REMOVING_WAITING"
StatusRemoved Status = "REMOVED"
StatusCancelingWaiting Status = "CANCELING_WAITING"
StatusCancelRejected Status = "CANCEL_REJECTED"
StatusFinishedCanceled Status = "FINISHED_CANCELED"
StatusFinishedError Status = "FINISHED_ERROR"
StatusFinishedSuccess Status = "FINISHED_SUCCESS"
StatusFinishedWarning Status = "FINISHED_WARNING"
StatusFinishedRejected Status = "FINISHED_REJECTED"
StatusStarted Status = "STARTED"
StatusDownloading Status = "DOWNLOADING"
StatusDownloadingWaiting Status = "DOWNLOADING_WAITING"
StatusDownloaded Status = "DOWNLOADED"
StatusDownloadedFileStored Status = "DOWNLOADED_FILE_STORED"
StatusInstalling Status = "INSTALLING"
StatusInstallingWaiting Status = "INSTALLING_WAITING"
StatusInstalled Status = "INSTALLED"
StatusRemoving Status = "REMOVING"
StatusRemovingWaiting Status = "REMOVING_WAITING"
StatusRemoved Status = "REMOVED"
StatusCancelingWaiting Status = "CANCELING_WAITING"
StatusCancelRejected Status = "CANCEL_REJECTED"
StatusFinishedCanceled Status = "FINISHED_CANCELED"
StatusFinishedError Status = "FINISHED_ERROR"
StatusFinishedSuccess Status = "FINISHED_SUCCESS"
StatusFinishedWarning Status = "FINISHED_WARNING"
StatusFinishedRejected Status = "FINISHED_REJECTED"
)
13 changes: 12 additions & 1 deletion hawkbit/software_updatable.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,16 @@ func MapLastOperation(LastOperationPtr *OperationStatus) map[string]interface{}
lastOperationMap[statusParam] = LastOperationPtr.Status

if LastOperationPtr.SoftwareModule != nil {
lastOperationMap[softwareModuleParam] = map[string]interface{}{
innerMap := map[string]interface{}{
softwareModuleNameParam: LastOperationPtr.SoftwareModule.Name,
softwareModuleVersionParam: LastOperationPtr.SoftwareModule.Version,
}

if LastOperationPtr.SoftwareModule.Path != "" {
innerMap[softwareModuleStoredPath] = LastOperationPtr.SoftwareModule.Path
}

lastOperationMap[softwareModuleParam] = innerMap
}

if LastOperationPtr.Software != nil {
Expand Down Expand Up @@ -195,3 +201,8 @@ func (su *SoftwareUpdatable) SetLastOperation(os *OperationStatus) error {
}
return su.setProperty(suPropertyLastOperation, MapLastOperation(su.status.LastOperation))
}

// GetLastStatus returns the recorded last operation status
func (su *SoftwareUpdatable) GetLastStatus() *OperationStatus {
return su.status.LastOperation
}
11 changes: 8 additions & 3 deletions internal/feature_download.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,14 @@ func (f *ScriptBasedSoftwareUpdatable) downloadModules(
}

// Archive all modules.
for i, module := range updatable.Modules {
if err := f.store.ArchiveModule(filepath.Join(toDir, strconv.Itoa(i))); err != nil {
logger.Errorf("failed to archive module [%s.%s]: %v", module.Name, module.Version, err)
if su.GetLastStatus().Status == hawkbit.StatusFinishedSuccess {
for i, module := range updatable.Modules {
if err := f.store.ArchiveModule(filepath.Join(toDir, strconv.Itoa(i)), &module.Path); err != nil {
logger.Errorf("failed to archive module [%s.%s]: %v", module.Name, module.Version, err)
} else {
logger.Debugf("Archived downloaded file path: %s", module.Path)
setLastOS(su, newOS(updatable.CorrelationID, module, hawkbit.StatusDownloadedFileStored))
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion internal/feature_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ func (f *ScriptBasedSoftwareUpdatable) fail(cid string, modules []*hawkbit.Softw
// newOS returns newly created OperationStatus pointer.
func newOS(cid string, module *storage.Module, status hawkbit.Status) *hawkbit.OperationStatus {
return hawkbit.NewOperationStatusUpdate(cid, status,
&hawkbit.SoftwareModuleID{Name: module.Name, Version: module.Version})
&hawkbit.SoftwareModuleID{Name: module.Name, Version: module.Version, Path: module.Path})
}

// newFileOS returns newly created OperationStatus pointer, filled with the status file data.
Expand Down
28 changes: 19 additions & 9 deletions internal/feature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,18 @@ func testDisconnectWhileRunningOperation(feature *ScriptBasedSoftwareUpdatable,
postDisconnectEventCount := 3 // DOWNLOADING(100)/INSTALLING(100), DOWNLOADED(100)/INSTALLED(100), FINISHED_SUCCESS
if install {
preDisconnectEventCount = 5 // STARTED, DOWNLOADING(0), DOWNLOADING(100), DOWNLOADED(100), INSTALLING(0)
} else {
postDisconnectEventCount = 4 // DOWNLOADING(100), DOWNLOADED(100), FINISHED_SUCCESS, DOWNLOADED_FILE_STORED
}
statuses := pullStatusChanges(mc, preDisconnectEventCount) // should go between DOWNLOADING/INSTALLING and next state

statuses := pullStatusChanges(mc, install, preDisconnectEventCount) // should go between DOWNLOADING/INSTALLING and next state

go func() { // decrements count number with 1, when disconnected
feature.Disconnect(false)
waitDisconnect.Done()
}()

statuses = append(statuses, pullStatusChanges(mc, postDisconnectEventCount)...)
statuses = append(statuses, pullStatusChanges(mc, install, postDisconnectEventCount)...)
waitDisconnect.Wait()
defer connectFeature(t, mc, feature, NewDefaultConfig().FeatureID)
if install {
Expand Down Expand Up @@ -310,13 +313,19 @@ func testScriptBasedSoftwareUpdatableOperationsLocal(t *testing.T, installDirs [
testDownloadInstall(feature, mc, artifacts, expectedSuccess, copyArtifacts, t)
}

func pullStatusChanges(mc *mockedClient, expectedCount int) []interface{} {
func pullStatusChanges(mc *mockedClient, install bool, expectedCount int) []interface{} {
var statuses []interface{}
for i := 0; i < expectedCount; i++ {
lo := mc.pullLastOperationStatus()
statuses = append(statuses, lo)
if lo["status"] == string(hawkbit.StatusFinishedSuccess) || lo["status"] == string(hawkbit.StatusFinishedError) {
break
if install {
if lo["status"] == string(hawkbit.StatusFinishedSuccess) || lo["status"] == string(hawkbit.StatusFinishedError) {
break
}
} else {
if lo["status"] == string(hawkbit.StatusDownloadedFileStored) || lo["status"] == string(hawkbit.StatusFinishedError) {
break
}
}
}
return statuses
Expand All @@ -334,7 +343,8 @@ func testDownloadInstall(feature *ScriptBasedSoftwareUpdatable, mc *mockedClient
// Try to execute a simple download operation.
feature.downloadHandler(sua, feature.su)

statuses := pullStatusChanges(mc, 5+extraDownloadingEventsCount) // STARTED, DOWNLOADING(0), DOWNLOADING(x extraDownloadingEventsCount), DOWNLOADING(100), DOWNLOADED(100), FINISHED_SUCCESS
// STARTED, DOWNLOADING(0), DOWNLOADING(x extraDownloadingEventsCount), DOWNLOADING(100), DOWNLOADED(100), FINISHED_SUCCESS, DOWNLOADED_FILE_STORED
statuses := pullStatusChanges(mc, false, 6+extraDownloadingEventsCount)
if expectedSuccess {
checkDownloadStatusEvents(extraDownloadingEventsCount, statuses, t)
if copyArtifacts == "" {
Expand All @@ -348,9 +358,8 @@ func testDownloadInstall(feature *ScriptBasedSoftwareUpdatable, mc *mockedClient

// Try to execute a simple install operation.
feature.installHandler(sua, feature.su)

statuses = pullStatusChanges(mc, 8+extraDownloadingEventsCount) // STARTED, DOWNLOADING(0), DOWNLOADING(x extraDownloadingEventsCount), DOWNLOADING(100), DOWNLOADED(100),
// INSTALLING(0), INSTALLING(100), INSTALLED(100), FINISHED_SUCCESS
// STARTED, DOWNLOADING(0), DOWNLOADING(x extraDownloadingEventsCount), DOWNLOADING(100), DOWNLOADED(100), INSTALLING(0), INSTALLING(100), INSTALLED(100), FINISHED_SUCCESS
statuses = pullStatusChanges(mc, true, 8+extraDownloadingEventsCount)
if expectedSuccess {
checkInstallStatusEvents(extraDownloadingEventsCount, statuses, t)
} else {
Expand Down Expand Up @@ -391,6 +400,7 @@ func checkDownloadStatusEvents(extraDownloadingEventsCount int, actualStatuses [
createStatus(hawkbit.StatusDownloading, completeProgress, noMessage),
createStatus(hawkbit.StatusDownloaded, completeProgress, noMessage),
createStatus(hawkbit.StatusFinishedSuccess, nil, noMessage),
createStatus(hawkbit.StatusDownloadedFileStored, nil, noMessage),
)
checkStatusEvents(expectedStatuses, actualStatuses, t)
}
Expand Down
4 changes: 3 additions & 1 deletion internal/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type Updatable struct {
type Module struct {
Name string `json:"name"`
Version string `json:"version"`
Path string `json:"path,omitempty"`
Artifacts []*Artifact `json:"artifacts,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
Expand Down Expand Up @@ -212,12 +213,13 @@ func (st *Storage) MoveInstalledDeps(dir string, metadata map[string]string) err
}

// ArchiveModule to modules directory.
func (st *Storage) ArchiveModule(dir string) error {
func (st *Storage) ArchiveModule(dir string, dest *string) error {
logger.Debugf("Archive module from directory: %s", dir)
path, err := FindAvailableLocation(st.ModulesPath)
if err != nil {
return err
}
*dest = path
if err := os.MkdirAll(path, 0755); err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion internal/storage/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,11 @@ func TestDownloadArchiveModule(t *testing.T) {
existence(filepath.Join(path, art.FileName), true, "[initial download]", t)

// 2. Archive module.
storedPath := ""
if err := WriteLn(filepath.Join(path, InternalStatusName), m.Name+":"+m.Version); err != nil {
t.Fatalf("fail to write module id: %v", err)
}
if err := store.ArchiveModule(path); err != nil {
if err := store.ArchiveModule(path, &storedPath); err != nil {
t.Fatalf("fail to archive module: %v", err)
}
existence(filepath.Join(store.ModulesPath, "0", art.FileName), true, "[archive]", t)
Expand Down