feat(system): path to upgrade swarm to BE [EE-4624] (#8124)
parent
b59a0ba823
commit
db9d87c918
|
@ -8,7 +8,6 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type systemUpgradePayload struct {
|
||||
|
@ -43,12 +42,10 @@ func (handler *Handler) systemUpgrade(w http.ResponseWriter, r *http.Request) *h
|
|||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
err = handler.upgradeService.Upgrade(payload.License)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed to upgrade Portainer")
|
||||
}
|
||||
}()
|
||||
err = handler.upgradeService.Upgrade(payload.License)
|
||||
if err != nil {
|
||||
return httperror.InternalServerError("Failed to upgrade Portainer", err)
|
||||
}
|
||||
|
||||
return response.Empty(w)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cbroglie/mustache"
|
||||
|
@ -17,8 +18,8 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
// mustacheUpgradeStandaloneTemplateFile represents the name of the template file for the standalone upgrade
|
||||
mustacheUpgradeStandaloneTemplateFile = "upgrade-standalone.yml.mustache"
|
||||
// mustacheUpgradeDockerTemplateFile represents the name of the template file for the docker upgrade
|
||||
mustacheUpgradeDockerTemplateFile = "upgrade-docker.yml.mustache"
|
||||
|
||||
// portainerImagePrefixEnvVar represents the name of the environment variable used to define the image prefix for portainer-updater
|
||||
// useful if there's a need to test PR images
|
||||
|
@ -60,19 +61,20 @@ func (service *service) Upgrade(licenseKey string) error {
|
|||
|
||||
switch service.platform {
|
||||
case platform.PlatformDockerStandalone:
|
||||
return service.UpgradeDockerStandalone(licenseKey, portainer.APIVersion)
|
||||
// case platform.PlatformDockerSwarm:
|
||||
return service.upgradeDocker(licenseKey, portainer.APIVersion, "standalone")
|
||||
case platform.PlatformDockerSwarm:
|
||||
return service.upgradeDocker(licenseKey, portainer.APIVersion, "swarm")
|
||||
// case platform.PlatformKubernetes:
|
||||
// case platform.PlatformPodman:
|
||||
// case platform.PlatformNomad:
|
||||
// default:
|
||||
}
|
||||
|
||||
return errors.New("unsupported platform")
|
||||
return fmt.Errorf("unsupported platform %s", service.platform)
|
||||
}
|
||||
|
||||
func (service *service) UpgradeDockerStandalone(licenseKey, version string) error {
|
||||
templateName := filesystem.JoinPaths(service.assetsPath, "mustache-templates", mustacheUpgradeStandaloneTemplateFile)
|
||||
func (service *service) upgradeDocker(licenseKey, version, envType string) error {
|
||||
templateName := filesystem.JoinPaths(service.assetsPath, "mustache-templates", mustacheUpgradeDockerTemplateFile)
|
||||
|
||||
portainerImagePrefix := os.Getenv(portainerImagePrefixEnvVar)
|
||||
if portainerImagePrefix == "" {
|
||||
|
@ -88,6 +90,7 @@ func (service *service) UpgradeDockerStandalone(licenseKey, version string) erro
|
|||
"skip_pull_image": skipPullImage,
|
||||
"updater_image": os.Getenv(updaterImageEnvVar),
|
||||
"license": licenseKey,
|
||||
"envType": envType,
|
||||
})
|
||||
|
||||
log.Debug().
|
||||
|
@ -99,7 +102,8 @@ func (service *service) UpgradeDockerStandalone(licenseKey, version string) erro
|
|||
}
|
||||
|
||||
tmpDir := os.TempDir()
|
||||
filePath := filesystem.JoinPaths(tmpDir, fmt.Sprintf("upgrade-%d.yml", time.Now().Unix()))
|
||||
timeId := time.Now().Unix()
|
||||
filePath := filesystem.JoinPaths(tmpDir, fmt.Sprintf("upgrade-%d.yml", timeId))
|
||||
|
||||
r := bytes.NewReader([]byte(composeFile))
|
||||
|
||||
|
@ -108,18 +112,28 @@ func (service *service) UpgradeDockerStandalone(licenseKey, version string) erro
|
|||
return errors.Wrap(err, "failed to create upgrade compose file")
|
||||
}
|
||||
|
||||
projectName := fmt.Sprintf(
|
||||
"portainer-upgrade-%d-%s",
|
||||
timeId,
|
||||
strings.Replace(version, ".", "-", -1))
|
||||
|
||||
err = service.composeDeployer.Deploy(
|
||||
context.Background(),
|
||||
[]string{filePath},
|
||||
libstack.DeployOptions{
|
||||
ForceRecreate: true,
|
||||
AbortOnContainerExit: true,
|
||||
Options: libstack.Options{
|
||||
ProjectName: projectName,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
// optimally, server was restarted by the updater, so we should not reach this point
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to deploy upgrade stack")
|
||||
}
|
||||
|
||||
return nil
|
||||
return errors.New("upgrade failed: server should have been restarted by the updater")
|
||||
}
|
||||
|
|
|
@ -74,3 +74,9 @@ function defaultErrorParser(axiosError: AxiosError) {
|
|||
const error = new Error(message);
|
||||
return { error, details };
|
||||
}
|
||||
|
||||
export function isAxiosError<
|
||||
ResponseType = { message: string; details: string }
|
||||
>(error: unknown): error is AxiosError<ResponseType> {
|
||||
return axiosOrigin.isAxiosError(error);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ export function useSystemStatus<T = StatusResponse>({
|
|||
select,
|
||||
enabled,
|
||||
retry,
|
||||
retryDelay: 1000,
|
||||
onSuccess,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { useMutation } from 'react-query';
|
||||
|
||||
import axios, { parseAxiosError } from '@/portainer/services/axios';
|
||||
import axios, {
|
||||
isAxiosError,
|
||||
parseAxiosError,
|
||||
} from '@/portainer/services/axios';
|
||||
import { withError } from '@/react-tools/react-query';
|
||||
|
||||
import { buildUrl } from './build-url';
|
||||
|
@ -15,6 +18,15 @@ async function upgradeEdition({ license }: { license: string }) {
|
|||
try {
|
||||
await axios.post(buildUrl('upgrade'), { license });
|
||||
} catch (error) {
|
||||
throw parseAxiosError(error as Error);
|
||||
if (!isAxiosError(error)) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
// if error is because the server disconnected, then everything went well
|
||||
if (!error.response || !error.response.status) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw parseAxiosError(error);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,10 @@ export const UpgradeBEBannerWrapper = withHideOnExtension(
|
|||
withEdition(UpgradeBEBanner, 'CE')
|
||||
);
|
||||
|
||||
const enabledPlatforms: Array<ContainerPlatform> = ['Docker Standalone'];
|
||||
const enabledPlatforms: Array<ContainerPlatform> = [
|
||||
'Docker Standalone',
|
||||
'Docker Swarm',
|
||||
];
|
||||
|
||||
function UpgradeBEBanner() {
|
||||
const { isAdmin } = useUser();
|
||||
|
|
|
@ -208,7 +208,7 @@ function shell_download_docker_compose_binary(platform, arch) {
|
|||
var binaryVersion = '<%= binaries.dockerComposePluginVersion %>';
|
||||
|
||||
return `
|
||||
if [ -f dist/docker-compose.plugin ] || [ -f dist/docker-compose.plugin.exe ]; then
|
||||
if [ -f dist/docker-compose ] || [ -f dist/docker-compose.exe ]; then
|
||||
echo "docker compose binary exists";
|
||||
else
|
||||
build/download_docker_compose_binary.sh ${platform} ${arch} ${binaryVersion};
|
||||
|
|
|
@ -5,7 +5,7 @@ services:
|
|||
image: {{updater_image}}{{^updater_image}}portainer/portainer-updater:latest{{/updater_image}}
|
||||
command: ["portainer",
|
||||
"--image", "{{image}}{{^image}}portainer/portainer-ee:latest{{/image}}",
|
||||
"--env-type", "standalone",
|
||||
"--env-type", "{{envType}}{{^envType}}standalone{{/envType}}",
|
||||
"--license", "{{license}}"
|
||||
]
|
||||
{{#skip_pull_image}}
|
Loading…
Reference in New Issue