From 50d1e9aa956327282781202c5d48f1b9077968af Mon Sep 17 00:00:00 2001 From: Nurlan Moldomurov Date: Mon, 21 Oct 2024 16:55:25 +0300 Subject: [PATCH] PMM-12573 Update podman via UI. (#3128) * PMM-12573 Update UI podman. * PMM-12573 Fix tests and linters. * PMM-12573 Added empty line at end of file. * PMM-12573 Simplify update logic. * PMM-12573 don't expose watchtower. * PMM-12573 change path of env file. * PMM-12573 Revert unnecessary changes. * PMM-12573 Refactoring. * PMM-12573 update watchtower config. * PMM-212573 fix path to watchtower env file. --- .../ansible/roles/podman-setup/tasks/main.yml | 8 +++++ .../podman-setup/templates/pmm-server.env | 4 +-- .../podman-setup/templates/pmm-server.service | 2 +- .../podman-setup/templates/watchtower.env | 5 +++ .../podman-setup/templates/watchtower.service | 13 ++----- docker-compose.yml | 6 ++++ managed/services/server/updater.go | 35 +++++++++++++++++++ managed/services/server/updater_test.go | 23 ++++++++++++ managed/testdata/updater/pmm-server.env | 4 +++ 9 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 build/packer/ansible/roles/podman-setup/templates/watchtower.env create mode 100644 managed/testdata/updater/pmm-server.env diff --git a/build/packer/ansible/roles/podman-setup/tasks/main.yml b/build/packer/ansible/roles/podman-setup/tasks/main.yml index 5c53c631cb..b7e9bf21fe 100644 --- a/build/packer/ansible/roles/podman-setup/tasks/main.yml +++ b/build/packer/ansible/roles/podman-setup/tasks/main.yml @@ -72,6 +72,14 @@ group: admin mode: '0644' +- name: Copy watchtower environment file for service to user-specific directory + template: + src: watchtower.env + dest: /home/admin/.config/systemd/user/ + owner: admin + group: admin + mode: '0644' + - name: Copy watchtower systemd service file to user-specific directory template: src: watchtower.service diff --git a/build/packer/ansible/roles/podman-setup/templates/pmm-server.env b/build/packer/ansible/roles/podman-setup/templates/pmm-server.env index 88936af0a7..1ffca72c01 100644 --- a/build/packer/ansible/roles/podman-setup/templates/pmm-server.env +++ b/build/packer/ansible/roles/podman-setup/templates/pmm-server.env @@ -1,5 +1,5 @@ PMM_WATCHTOWER_HOST=http://watchtower:8080 PMM_WATCHTOWER_TOKEN=123 -PMM_SERVER_UPDATE_VERSION=docker.io/perconalab/pmm-server:3-dev-container +PMM_DEV_UPDATE_DOCKER_IMAGE=docker.io/perconalab/pmm-server:3-dev-container PMM_IMAGE={{ pmm_server_image_name }} -PMM_DISTRIBUTION_METHOD={{ pmm_distribution_method }} \ No newline at end of file +PMM_DISTRIBUTION_METHOD={{ pmm_distribution_method }} diff --git a/build/packer/ansible/roles/podman-setup/templates/pmm-server.service b/build/packer/ansible/roles/podman-setup/templates/pmm-server.service index dc862129e3..af733ad998 100644 --- a/build/packer/ansible/roles/podman-setup/templates/pmm-server.service +++ b/build/packer/ansible/roles/podman-setup/templates/pmm-server.service @@ -14,7 +14,7 @@ RestartSec=20 ExecStart=/usr/bin/podman run \ --volume /home/admin/volume/srv:/srv \ --volume /home/admin/.ssh/:/home/pmm/.ssh/ \ - --volume /home/admin/.config/:/home/pmm/config/ \ + --volume /home/admin/.config/systemd/user/:/home/pmm/update/ \ --rm --replace=true --name %N \ --env-file=/home/admin/.config/systemd/user/pmm-server.env \ --net pmm_default \ diff --git a/build/packer/ansible/roles/podman-setup/templates/watchtower.env b/build/packer/ansible/roles/podman-setup/templates/watchtower.env new file mode 100644 index 0000000000..727aa953fe --- /dev/null +++ b/build/packer/ansible/roles/podman-setup/templates/watchtower.env @@ -0,0 +1,5 @@ +WATCHTOWER_HTTP_API_UPDATE=1 +WATCHTOWER_HTTP_API_TOKEN=123 +WATCHTOWER_NO_RESTART=1 +WATCHTOWER_DEBUG=1 +WATCHTOWER_CLEANUP=1 \ No newline at end of file diff --git a/build/packer/ansible/roles/podman-setup/templates/watchtower.service b/build/packer/ansible/roles/podman-setup/templates/watchtower.service index 96c1e93202..7fc366d86b 100644 --- a/build/packer/ansible/roles/podman-setup/templates/watchtower.service +++ b/build/packer/ansible/roles/podman-setup/templates/watchtower.service @@ -8,21 +8,14 @@ After=time-sync.target [Service] Restart=on-failure RestartSec=20 - -Environment=WATCHTOWER_HTTP_API_UPDATE=1 -Environment=WATCHTOWER_HTTP_API_TOKEN=123 -Environment=WATCHTOWER_NO_RESTART=1 -Environment=WATCHTOWER_DEBUG=1 +EnvironmentFile=/home/admin/.config/systemd/user/watchtower.env ExecStart=/usr/bin/podman run --rm --replace=true --name %N \ -v ${XDG_RUNTIME_DIR}/podman/podman.sock:/var/run/docker.sock \ - -e WATCHTOWER_HTTP_API_UPDATE=${WATCHTOWER_HTTP_API_UPDATE} \ - -e WATCHTOWER_HTTP_API_TOKEN=${WATCHTOWER_HTTP_API_TOKEN} \ - -e WATCHTOWER_NO_RESTART=${WATCHTOWER_NO_RESTART} \ - -e WATCHTOWER_DEBUG=${WATCHTOWER_DEBUG} \ + --env-file=/home/admin/.config/systemd/user/watchtower.env \ --net pmm_default \ --cap-add=net_admin,net_raw \ - -p 8080:8080/tcp docker.io/perconalab/watchtower + docker.io/perconalab/watchtower ExecStop=/usr/bin/podman stop -t 10 %N diff --git a/docker-compose.yml b/docker-compose.yml index 06341c92cd..8ae3910cc3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,7 +25,11 @@ services: - PMM_WATCHTOWER_HOST=${PMM_WATCHTOWER_HOST:-http://watchtower:8080} - PMM_WATCHTOWER_TOKEN=${PMM_WATCHTOWER_TOKEN:-INSECURE_TOKEN} - PMM_RELEASE_VERSION=3.0.0-alpha + # - PMM_DISTRIBUTION_METHOD=${PMM_DISTRIBUTION_METHOD:-docker} + - PMM_DEV_UPDATE_DOCKER_IMAGE=${PMM_DEV_UPDATE_DOCKER_IMAGE:-} # - PMM_DEV_VERSION_SERVICE_URL=http://localhost:11000 + # - PMM_DEV_PERCONA_PLATFORM_ADDRESS=https://check.localhost + # - PMM_DEV_PERCONA_PLATFORM_INSECURE=1 # - PMM_DEV_PERCONA_PLATFORM_PUBLIC_KEY= # - PMM_DEV_TELEMETRY_INTERVAL=10s # - PMM_DEV_TELEMETRY_DISABLE_START_DELAY=1 @@ -80,6 +84,7 @@ services: volumes: - ./:/root/go/src/github.com/percona/pmm - ./Makefile.devcontainer:/root/go/src/github.com/percona/pmm/Makefile:ro # substitute Makefile in devcontainer + - ./managed/testdata/updater/:/home/pmm/.config/systemd/user/ # caching - go-modules:/root/go/pkg/mod - root-cache:/root/.cache @@ -103,6 +108,7 @@ services: - WATCHTOWER_HTTP_LISTEN_PORT=8080 - WATCHTOWER_HTTP_API_UPDATE=1 - WATCHTOWER_HTTP_API_TOKEN=${PMM_WATCHTOWER_TOKEN:-INSECURE_TOKEN} + - WATCHTOWER_NO_RESTART=${WATCHTOWER_NO_RESTART:-0} hostname: watchtower networks: - ${NETWORK:-default} diff --git a/managed/services/server/updater.go b/managed/services/server/updater.go index 9c6bc12f33..bbe96f8130 100644 --- a/managed/services/server/updater.go +++ b/managed/services/server/updater.go @@ -46,6 +46,7 @@ const ( updateCheckInterval = 24 * time.Hour updateCheckResultFresh = updateCheckInterval + 10*time.Minute updateDefaultTimeout = 30 * time.Second + envfilePath = "/home/pmm/update/pmm-server.env" ) var fileName = "/etc/pmm-server-update-version.json" @@ -173,6 +174,19 @@ func (up *Updater) StartUpdate(ctx context.Context, newImageName string) error { return grpcstatus.Errorf(codes.FailedPrecondition, "failed to check watchtower host") } + if _, e := os.Stat(envfilePath); e == nil { + err := up.updatePodmanEnvironmentVariables(envfilePath, newImageName) + if err != nil { + up.running = false + up.l.WithError(err).Error("Failed to update environment variables file") + return errors.Wrap(err, "failed to update environment variables file") + } + } else if !os.IsNotExist(e) { + up.running = false + up.l.WithError(e).Error("Failed to check environment variables file") + return errors.Wrap(e, "failed to check environment variables file") + } + if err := up.sendRequestToWatchtower(ctx, newImageName); err != nil { up.running = false up.l.WithError(err).Error("Failed to trigger update") @@ -475,6 +489,27 @@ func (up *Updater) checkWatchtowerHost() error { return nil } +func (up *Updater) updatePodmanEnvironmentVariables(filename string, name string) error { + if len(strings.Split(name, "/")) < 3 { + name = "docker.io/" + name + } + file, err := os.ReadFile(filename) + if err != nil { + return errors.Wrap(err, "failed to read file") + } + lines := strings.Split(string(file), "\n") + for i, line := range lines { + if strings.Contains(line, "PMM_IMAGE") { + lines[i] = fmt.Sprintf("PMM_IMAGE=%s", name) + } + } + err = os.WriteFile(filename, []byte(strings.Join(lines, "\n")), 0o644) + if err != nil { + return errors.Wrap(err, "failed to write file") + } + return nil +} + func isHostAvailable(host string, port string, timeout time.Duration) bool { conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, port), timeout) if err != nil { diff --git a/managed/services/server/updater_test.go b/managed/services/server/updater_test.go index 8d5ff848c7..ddb591dd54 100644 --- a/managed/services/server/updater_test.go +++ b/managed/services/server/updater_test.go @@ -35,6 +35,7 @@ import ( func TestUpdater(t *testing.T) { gRPCMessageMaxSize := uint32(100 * 1024 * 1024) watchtowerURL, _ := url.Parse("http://watchtower:8080") + const tmpDistributionFile = "/tmp/distribution" t.Run("TestNextVersion", func(t *testing.T) { type args struct { @@ -292,4 +293,26 @@ func TestUpdater(t *testing.T) { assert.Equal(t, "2.41.1", latest.DockerImage) assert.Equal(t, time.Date(2024, 3, 20, 15, 48, 7, 145620000, time.UTC), latest.BuildTime) }) + + t.Run("TestUpdateEnvFile", func(t *testing.T) { + u := NewUpdater(watchtowerURL, gRPCMessageMaxSize) + tmpFile := filepath.Join(os.TempDir(), "pmm-service.env") + content := `PMM_WATCHTOWER_HOST=http://watchtower:8080 +PMM_WATCHTOWER_TOKEN=123 +PMM_SERVER_UPDATE_VERSION=docker.io/perconalab/pmm-server:3-dev-container +PMM_IMAGE=docker.io/perconalab/pmm-server:3-dev-latest +PMM_DISTRIBUTION_METHOD=ami` + err := os.WriteFile(tmpFile, []byte(content), 0o644) + require.NoError(t, err) + + err = u.updatePodmanEnvironmentVariables(tmpFile, "perconalab/pmm-server:3-dev-container") + require.NoError(t, err) + newContent, err := os.ReadFile(tmpFile) + require.NoError(t, err) + assert.Equal(t, `PMM_WATCHTOWER_HOST=http://watchtower:8080 +PMM_WATCHTOWER_TOKEN=123 +PMM_SERVER_UPDATE_VERSION=docker.io/perconalab/pmm-server:3-dev-container +PMM_IMAGE=docker.io/perconalab/pmm-server:3-dev-container +PMM_DISTRIBUTION_METHOD=ami`, string(newContent)) + }) } diff --git a/managed/testdata/updater/pmm-server.env b/managed/testdata/updater/pmm-server.env new file mode 100644 index 0000000000..d136bf149d --- /dev/null +++ b/managed/testdata/updater/pmm-server.env @@ -0,0 +1,4 @@ +PMM_WATCHTOWER_HOST=http://watchtower:8080 +PMM_WATCHTOWER_TOKEN=123 +PMM_IMAGE=docker.io/perconalab/pmm-server:3-dev-latest +PMM_DISTRIBUTION_METHOD=ami