Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PMM-12573 Update podman via UI. #3128

Open
wants to merge 12 commits into
base: v3
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -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
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will be dropped before GA

PMM_IMAGE={{ pmm_server_image_name }}
PMM_DISTRIBUTION_METHOD={{ pmm_distribution_method }}
PMM_DISTRIBUTION_METHOD={{ pmm_distribution_method }}
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ ExecStart=/usr/bin/podman run --rm --replace=true --name %N \
-e WATCHTOWER_DEBUG=${WATCHTOWER_DEBUG} \
--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

Expand Down
4 changes: 4 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ 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_PERCONA_PLATFORM_ADDRESS=https://check.localhost
# - PMM_DEV_PERCONA_PLATFORM_INSECURE=1
# - PMM_DEV_PERCONA_PLATFORM_PUBLIC_KEY=<public key>
Expand Down Expand Up @@ -81,6 +83,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
Expand All @@ -104,6 +107,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}
Expand Down
4 changes: 2 additions & 2 deletions managed/cmd/pmm-managed/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,8 @@ func main() { //nolint:maintidx,cyclop
connectionCheck := agents.NewConnectionChecker(agentsRegistry)
serviceInfoBroker := agents.NewServiceInfoBroker(agentsRegistry)

updater := server.NewUpdater(*watchtowerHostF, gRPCMessageMaxSize)
dus := distribution.NewService(distributionInfoFilePath, osInfoFilePath, l)
updater := server.NewUpdater(*watchtowerHostF, dus, gRPCMessageMaxSize)

logs := server.NewLogs(version.FullInfo(), updater, vmParams)

Expand Down Expand Up @@ -896,7 +897,6 @@ func main() { //nolint:maintidx,cyclop
telemetry.UIEventsExtension: uieventsService,
}

dus := distribution.NewService(distributionInfoFilePath, osInfoFilePath, l)
telemetry, err := telemetry.NewService(db, platformClient, version.Version, dus, cfg.Config.Services.Telemetry, telemetryExtensions)
if err != nil {
l.Fatalf("Could not create telemetry service: %s", err)
Expand Down
41 changes: 40 additions & 1 deletion managed/services/server/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"google.golang.org/grpc/codes"
grpcstatus "google.golang.org/grpc/status"

"github.com/percona/pmm/managed/utils/distribution"
"github.com/percona/pmm/version"
)

Expand All @@ -44,6 +45,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"
Expand All @@ -52,6 +54,7 @@ var fileName = "/etc/pmm-server-update-version.json"
type Updater struct {
l *logrus.Entry
watchtowerHost *url.URL
dus *distribution.Service
gRPCMessageMaxSize uint32

performM sync.Mutex
Expand All @@ -63,10 +66,11 @@ type Updater struct {
}

// NewUpdater creates a new Updater service.
func NewUpdater(watchtowerHost *url.URL, gRPCMessageMaxSize uint32) *Updater {
func NewUpdater(watchtowerHost *url.URL, dus *distribution.Service, gRPCMessageMaxSize uint32) *Updater {
u := &Updater{
l: logrus.WithField("service", "updater"),
watchtowerHost: watchtowerHost,
dus: dus,
gRPCMessageMaxSize: gRPCMessageMaxSize,
}
return u
Expand Down Expand Up @@ -157,6 +161,20 @@ func (up *Updater) StartUpdate(ctx context.Context, newImageName string) error {
return grpcstatus.Errorf(codes.FailedPrecondition, "failed to check watchtower host")
}

fileInfo, err := os.Stat(envfilePath)
if os.IsExist(err) && fileInfo != nil {
err := up.updateEnvironmentVariables(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 err != nil {
up.running = false
up.l.WithError(err).Error("Failed to check file")
return errors.Wrap(err, "failed to check file")
}

if err := up.sendRequestToWatchtower(ctx, newImageName); err != nil {
up.l.WithError(err).Error("Failed to trigger update")
return errors.Wrap(err, "failed to trigger update")
Expand Down Expand Up @@ -409,6 +427,27 @@ func (up *Updater) checkWatchtowerHost() error {
return nil
}

func (up *Updater) updateEnvironmentVariables(filename string, name string) error {
if len(strings.Split(name, "/")) < 3 {
name = "docker.io/" + name
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

podman requires full name to update.

}
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 {
Expand Down
32 changes: 29 additions & 3 deletions managed/services/server/updater_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,19 @@ import (
"time"

"github.com/AlekSi/pointer"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/percona/pmm/managed/utils/distribution"
"github.com/percona/pmm/version"
)

func TestUpdater(t *testing.T) {
gRPCMessageMaxSize := uint32(100 * 1024 * 1024)
watchtowerURL, _ := url.Parse("http://watchtower:8080")
const tmpDistributionFile = "/tmp/distribution"
dus := distribution.NewService(tmpDistributionFile, "/proc/version", logrus.WithField("test", "true"))

t.Run("TestNextVersion", func(t *testing.T) {
type args struct {
Expand Down Expand Up @@ -230,7 +234,7 @@ func TestUpdater(t *testing.T) {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
u := NewUpdater(watchtowerURL, gRPCMessageMaxSize)
u := NewUpdater(watchtowerURL, dus, gRPCMessageMaxSize)
parsed, err := version.Parse(tt.args.currentVersion)
require.NoError(t, err)
next := u.next(*parsed, tt.args.results)
Expand All @@ -247,7 +251,7 @@ func TestUpdater(t *testing.T) {

t.Run("TestLatest", func(t *testing.T) {
version.Version = "2.41.0"
u := NewUpdater(watchtowerURL, gRPCMessageMaxSize)
u := NewUpdater(watchtowerURL, dus, gRPCMessageMaxSize)
latest, err := u.latest(context.Background())
require.NoError(t, err)
assert.NotNil(t, latest)
Expand All @@ -264,11 +268,33 @@ func TestUpdater(t *testing.T) {
err := os.WriteFile(fileName, []byte(fileBody), 0o600)
require.NoError(t, err)

u := NewUpdater(watchtowerURL, gRPCMessageMaxSize)
u := NewUpdater(watchtowerURL, dus, gRPCMessageMaxSize)
latest, err := u.latest(context.Background())
require.NoError(t, err)
assert.Equal(t, "2.41.1", latest.Version.String())
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, dus, 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.updateEnvironmentVariables(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))
})
}
4 changes: 4 additions & 0 deletions managed/testdata/updater/pmm-server.env
Original file line number Diff line number Diff line change
@@ -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
Loading