mirror of https://github.com/jetkvm/kvm.git
fix: should return error if version is not available
This commit is contained in:
parent
252dcba7a1
commit
329ad025bf
|
|
@ -0,0 +1,8 @@
|
||||||
|
package ota
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrVersionNotFound is returned when the specified version is not found
|
||||||
|
ErrVersionNotFound = errors.New("specified version not found")
|
||||||
|
)
|
||||||
|
|
@ -3,6 +3,7 @@ package ota
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
@ -23,12 +24,14 @@ func (s *State) GetReleaseAPIEndpoint() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getUpdateURL returns the update URL for the given parameters
|
// getUpdateURL returns the update URL for the given parameters
|
||||||
func (s *State) getUpdateURL(params UpdateParams) (string, error) {
|
func (s *State) getUpdateURL(params UpdateParams) (string, error, bool) {
|
||||||
updateURL, err := url.Parse(s.releaseAPIEndpoint)
|
updateURL, err := url.Parse(s.releaseAPIEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("error parsing update metadata URL: %w", err)
|
return "", fmt.Errorf("error parsing update metadata URL: %w", err), false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isCustomVersion := false
|
||||||
|
|
||||||
appTargetVersion := s.GetTargetVersion("app")
|
appTargetVersion := s.GetTargetVersion("app")
|
||||||
if appTargetVersion != "" && params.AppTargetVersion == "" {
|
if appTargetVersion != "" && params.AppTargetVersion == "" {
|
||||||
params.AppTargetVersion = appTargetVersion
|
params.AppTargetVersion = appTargetVersion
|
||||||
|
|
@ -43,19 +46,21 @@ func (s *State) getUpdateURL(params UpdateParams) (string, error) {
|
||||||
query.Set("prerelease", fmt.Sprintf("%v", params.IncludePreRelease))
|
query.Set("prerelease", fmt.Sprintf("%v", params.IncludePreRelease))
|
||||||
if params.AppTargetVersion != "" {
|
if params.AppTargetVersion != "" {
|
||||||
query.Set("appVersion", params.AppTargetVersion)
|
query.Set("appVersion", params.AppTargetVersion)
|
||||||
|
isCustomVersion = true
|
||||||
}
|
}
|
||||||
if params.SystemTargetVersion != "" {
|
if params.SystemTargetVersion != "" {
|
||||||
query.Set("systemVersion", params.SystemTargetVersion)
|
query.Set("systemVersion", params.SystemTargetVersion)
|
||||||
|
isCustomVersion = true
|
||||||
}
|
}
|
||||||
updateURL.RawQuery = query.Encode()
|
updateURL.RawQuery = query.Encode()
|
||||||
|
|
||||||
return updateURL.String(), nil
|
return updateURL.String(), nil, isCustomVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) fetchUpdateMetadata(ctx context.Context, params UpdateParams) (*UpdateMetadata, error) {
|
func (s *State) fetchUpdateMetadata(ctx context.Context, params UpdateParams) (*UpdateMetadata, error) {
|
||||||
metadata := &UpdateMetadata{}
|
metadata := &UpdateMetadata{}
|
||||||
|
|
||||||
url, err := s.getUpdateURL(params)
|
url, err, isCustomVersion := s.getUpdateURL(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error getting update URL: %w", err)
|
return nil, fmt.Errorf("error getting update URL: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -77,6 +82,10 @@ func (s *State) fetchUpdateMetadata(ctx context.Context, params UpdateParams) (*
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if isCustomVersion && resp.StatusCode == http.StatusNotFound {
|
||||||
|
return nil, ErrVersionNotFound
|
||||||
|
}
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
@ -189,7 +198,7 @@ func (s *State) doUpdate(ctx context.Context, params UpdateParams) error {
|
||||||
|
|
||||||
postRebootAction := &PostRebootAction{
|
postRebootAction := &PostRebootAction{
|
||||||
HealthCheck: "/device/status",
|
HealthCheck: "/device/status",
|
||||||
RedirectUrl: redirectUrl,
|
RedirectTo: redirectUrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.reboot(true, postRebootAction, 10*time.Second); err != nil {
|
if err := s.reboot(true, postRebootAction, 10*time.Second); err != nil {
|
||||||
|
|
@ -241,7 +250,11 @@ func (s *State) getUpdateStatus(
|
||||||
// Get remote metadata
|
// Get remote metadata
|
||||||
remoteMetadata, err := s.fetchUpdateMetadata(ctx, params)
|
remoteMetadata, err := s.fetchUpdateMetadata(ctx, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("error checking for updates: %w", err)
|
if err == ErrVersionNotFound || errors.Unwrap(err) == ErrVersionNotFound {
|
||||||
|
err = ErrVersionNotFound
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("error checking for updates: %w", err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
appUpdate.url = remoteMetadata.AppURL
|
appUpdate.url = remoteMetadata.AppURL
|
||||||
|
|
|
||||||
31
ota.go
31
ota.go
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Masterminds/semver/v3"
|
"github.com/Masterminds/semver/v3"
|
||||||
"github.com/jetkvm/kvm/internal/ota"
|
"github.com/jetkvm/kvm/internal/ota"
|
||||||
|
|
@ -158,11 +159,15 @@ func rpcTryUpdateComponents(components tryUpdateComponents, includePreRelease bo
|
||||||
|
|
||||||
logger.Info().Interface("components", components).Msg("components")
|
logger.Info().Interface("components", components).Msg("components")
|
||||||
|
|
||||||
|
currentAppTargetVersion := otaState.GetTargetVersion("app")
|
||||||
|
appTargetVersionChanged := currentAppTargetVersion != components.AppTargetVersion
|
||||||
updateParams.AppTargetVersion = components.AppTargetVersion
|
updateParams.AppTargetVersion = components.AppTargetVersion
|
||||||
if err := otaState.SetTargetVersion("app", components.AppTargetVersion); err != nil {
|
if err := otaState.SetTargetVersion("app", components.AppTargetVersion); err != nil {
|
||||||
return fmt.Errorf("failed to set app target version: %w", err)
|
return fmt.Errorf("failed to set app target version: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentSystemTargetVersion := otaState.GetTargetVersion("system")
|
||||||
|
systemTargetVersionChanged := currentSystemTargetVersion != components.SystemTargetVersion
|
||||||
updateParams.SystemTargetVersion = components.SystemTargetVersion
|
updateParams.SystemTargetVersion = components.SystemTargetVersion
|
||||||
if err := otaState.SetTargetVersion("system", components.SystemTargetVersion); err != nil {
|
if err := otaState.SetTargetVersion("system", components.SystemTargetVersion); err != nil {
|
||||||
return fmt.Errorf("failed to set system target version: %w", err)
|
return fmt.Errorf("failed to set system target version: %w", err)
|
||||||
|
|
@ -172,6 +177,32 @@ func rpcTryUpdateComponents(components tryUpdateComponents, includePreRelease bo
|
||||||
updateParams.Components = strings.Split(components.Components, ",")
|
updateParams.Components = strings.Split(components.Components, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if it's a check only update, we don't need to try to update, we just need to check if the version is available
|
||||||
|
// and return the error immediately then revert the previous target versions
|
||||||
|
if checkOnly {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
_, err := otaState.GetUpdateStatus(ctx, updateParams)
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// revert the previous target versions
|
||||||
|
if appTargetVersionChanged {
|
||||||
|
if err := otaState.SetTargetVersion("app", currentAppTargetVersion); err != nil {
|
||||||
|
return fmt.Errorf("failed to revert app target version: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if systemTargetVersionChanged {
|
||||||
|
if err := otaState.SetTargetVersion("system", currentSystemTargetVersion); err != nil {
|
||||||
|
return fmt.Errorf("failed to revert system target version: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err := otaState.TryUpdate(context.Background(), updateParams)
|
err := otaState.TryUpdate(context.Background(), updateParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { useCallback, useMemo } from "react";
|
import { useCallback } from "react";
|
||||||
import semver from "semver";
|
|
||||||
|
|
||||||
import { useDeviceStore } from "@/hooks/stores";
|
import { useDeviceStore } from "@/hooks/stores";
|
||||||
import { JsonRpcError, RpcMethodNotFound } from "@/hooks/useJsonRpc";
|
import { JsonRpcError, RpcMethodNotFound } from "@/hooks/useJsonRpc";
|
||||||
|
|
@ -69,6 +68,5 @@ export function useVersion() {
|
||||||
getLocalVersion,
|
getLocalVersion,
|
||||||
appVersion,
|
appVersion,
|
||||||
systemVersion,
|
systemVersion,
|
||||||
isOnDevVersion,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,9 @@ export interface SystemVersionInfo {
|
||||||
local: VersionInfo;
|
local: VersionInfo;
|
||||||
remote?: VersionInfo;
|
remote?: VersionInfo;
|
||||||
systemUpdateAvailable: boolean;
|
systemUpdateAvailable: boolean;
|
||||||
|
systemDowngradeAvailable: boolean;
|
||||||
appUpdateAvailable: boolean;
|
appUpdateAvailable: boolean;
|
||||||
|
appDowngradeAvailable: boolean;
|
||||||
error?: string;
|
error?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue