Skip to content

Commit 168a536

Browse files
egeguneshorsgithub-actions[bot]
authored
K8SPG-375: Support installing custom extensions (#533)
* K8SPG-375: Support installing custom extensions * fix installer if there's no installed extension * add test * fix test * add telemetry * address review comments * check available extensions in test * improve test * fix * Update build/extension-installer/install-extensions.sh Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * debug * fix * fix golicense * increase timeouts * debug * please make it stop * Revert "debug" This reverts commit 085f25d. * Revert "debug" This reverts commit b0610a3. * improve test * fix extension uninstall * add section to enable/disable builtin extensions * fix test * im bored of this sh*t * fix golangci-lint * fix unit tests * Update e2e-tests/functions Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update e2e-tests/functions Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update e2e-tests/functions Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update e2e-tests/functions Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update e2e-tests/functions Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update e2e-tests/functions Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update e2e-tests/functions Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update e2e-tests/functions Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update e2e-tests/functions Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update e2e-tests/functions Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update e2e-tests/functions Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * fix e2e-tests/functions * fix golangci-lint * fix --------- Co-authored-by: Viacheslav Sarzhan <[email protected]> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 98f7ea6 commit 168a536

File tree

81 files changed

+61780
-40849
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+61780
-40849
lines changed

Jenkinsfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
251251
EOF
252252
sudo yum install -y google-cloud-cli google-cloud-cli-gke-gcloud-auth-plugin
253253
254-
curl -sL https://github.com/mitchellh/golicense/releases/latest/download/golicense_0.2.0_linux_x86_64.tar.gz | sudo tar -C /usr/local/bin -xzf - golicense
254+
curl -sL https://github.com/mitchellh/golicense/releases/download/v0.2.0/golicense_0.2.0_linux_x86_64.tar.gz | sudo tar -C /usr/local/bin -xzf - golicense
255255
"""
256256
}
257257

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,9 @@ envtest: ## Download envtest-setup locally if necessary.
351351
build-docker-image:
352352
ROOT_REPO=$(ROOT_REPO) VERSION=$(VERSION) IMAGE=$(IMAGE) $(ROOT_REPO)/e2e-tests/build
353353

354+
build-extension-installer-image:
355+
ROOT_REPO=$(ROOT_REPO) VERSION=$(VERSION) IMAGE=$(IMAGE)-ext-installer COMPONENT=extension-installer $(ROOT_REPO)/e2e-tests/build
356+
354357
generate: kustomize generate-crd generate-deepcopy generate-rbac generate-manager generate-bundle generate-cw
355358

356359
generate-crd: generate-crunchy-crd generate-percona-crd

build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml

Lines changed: 1612 additions & 211 deletions
Large diffs are not rendered by default.

build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml

Lines changed: 1664 additions & 173 deletions
Large diffs are not rendered by default.

build/extension-installer/Dockerfile

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
FROM golang:1.20 AS go_builder
2+
WORKDIR /go/src/github.com/percona/percona-postgresql-operator
3+
4+
COPY . .
5+
RUN go mod download
6+
7+
ARG GIT_COMMIT
8+
ARG GIT_BRANCH
9+
ARG GO_LDFLAGS
10+
ARG GOOS=linux
11+
ARG GOARCH=amd64
12+
ARG CGO_ENABLED=0
13+
14+
RUN mkdir -p build/_output/bin \
15+
&& CGO_ENABLED=$CGO_ENABLED GOOS=$GOOS GOARCH=$GOARCH GO_LDFLAGS=$GO_LDFLAGS \
16+
go build -ldflags "-w -s -X main.GitCommit=$GIT_COMMIT -X main.GitBranch=$GIT_BRANCH" \
17+
-o build/_output/bin/extension-installer \
18+
./cmd/extension-installer \
19+
&& cp -r build/_output/bin/extension-installer /usr/local/bin/extension-installer
20+
21+
22+
RUN ./bin/license_aggregator.sh ./cmd/...; \
23+
cp -r ./licenses /licenses
24+
25+
FROM registry.access.redhat.com/ubi9/ubi-minimal AS ubi9
26+
27+
LABEL name="Percona Postgres Operator Custom Extension Installer" \
28+
vendor="Percona" \
29+
summary="Percona Postgres Operator performs Postgres database creation, adjustment and maintenance inside Kubernetes cluster" \
30+
description="Percona Postgres Operator simplifies and automates all essential actions for stable and continuous database operation during the whole database lifecycle" \
31+
maintainer="Percona Development <[email protected]>"
32+
33+
RUN microdnf update -y && microdnf clean all -y
34+
35+
COPY licenses /licenses
36+
37+
COPY --from=go_builder /usr/local/bin/extension-installer /usr/local/bin
38+
COPY --from=go_builder /licenses /licenses
39+
COPY build/extension-installer/install-extensions.sh /usr/local/bin
40+
41+
USER 26
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/bin/bash
2+
3+
set -e
4+
set -o xtrace
5+
6+
IFS=',' read -ra extensions <<<"$INSTALL_EXTENSIONS"
7+
for key in "${extensions[@]}"; do
8+
if [ -f ${PGDATA_EXTENSIONS}/${key}.installed ]; then
9+
echo "Extension ${key} already installed"
10+
continue
11+
fi
12+
13+
echo "Installing extension: ${key}"
14+
/usr/local/bin/extension-installer \
15+
-type ${STORAGE_TYPE} \
16+
-region ${STORAGE_REGION} \
17+
-bucket ${STORAGE_BUCKET} \
18+
-extension-path ${PGDATA_EXTENSIONS} \
19+
-key ${key} \
20+
-install
21+
done
22+
23+
for installed in ${PGDATA_EXTENSIONS}/*.installed; do
24+
filename=$(basename -- ${installed})
25+
key=${filename%.*}
26+
if [[ ${key} == "*" ]]; then
27+
continue
28+
fi
29+
30+
if [[ ! ${extensions[*]} =~ ${key} ]]; then
31+
echo "Uninstalling extension: ${key}"
32+
/usr/local/bin/extension-installer \
33+
-type ${STORAGE_TYPE} \
34+
-region ${STORAGE_REGION} \
35+
-bucket ${STORAGE_BUCKET} \
36+
-extension-path ${PGDATA_EXTENSIONS} \
37+
-key ${key} \
38+
-uninstall
39+
rm -f ${installed}
40+
fi
41+
done

cmd/extension-installer/main.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"io"
6+
"log"
7+
"os"
8+
"path"
9+
10+
"github.com/percona/percona-postgresql-operator/percona/extensions"
11+
)
12+
13+
func main() {
14+
var storageType, region, bucket, key, extensionPath string
15+
var install, uninstall bool
16+
17+
flag.StringVar(&storageType, "type", "", "Storage type")
18+
flag.StringVar(&region, "region", "", "Storage region")
19+
flag.StringVar(&bucket, "bucket", "", "Storage bucket")
20+
flag.StringVar(&extensionPath, "extension-path", "", "Extension installation path")
21+
flag.StringVar(&key, "key", "", "Extension archive key")
22+
23+
flag.BoolVar(&install, "install", false, "Install extension")
24+
flag.BoolVar(&uninstall, "uninstall", false, "Uninstall extension")
25+
flag.Parse()
26+
27+
if (install && uninstall) || (!install && !uninstall) {
28+
log.Fatalf("ERROR: set either -install or -uninstall")
29+
}
30+
31+
log.Printf("starting extension installer for %s/%s (%s) in %s", bucket, key, storageType, region)
32+
33+
storage := initStorage(extensions.StorageType(storageType), bucket, region)
34+
35+
packageName := key + ".tar.gz"
36+
37+
object, err := storage.Get(packageName)
38+
if err != nil {
39+
log.Fatalf("ERROR: failed to get object: %v", err)
40+
}
41+
42+
archivePath := path.Join("/tmp", packageName)
43+
44+
// TODO: /tmp is not a good place due to its size limitation.
45+
dst, err := os.Create(archivePath)
46+
if err != nil {
47+
log.Fatalf("ERROR: failed to create file: %v", err)
48+
}
49+
defer dst.Close()
50+
51+
written, err := io.Copy(dst, object)
52+
if err != nil {
53+
log.Fatalf("ERROR: failed to copy object: %v", err)
54+
}
55+
56+
log.Printf("copied %d bytes to %s", written, dst.Name())
57+
58+
switch {
59+
case install:
60+
log.Printf("installing extension %s", archivePath)
61+
if err := extensions.Install(key, archivePath, extensionPath); err != nil {
62+
log.Fatalf("ERROR: failed to install extension: %v", err)
63+
}
64+
case uninstall:
65+
log.Printf("uninstalling extension %s", archivePath)
66+
if err := extensions.Uninstall(archivePath); err != nil {
67+
log.Fatalf("ERROR: failed to uninstall extension: %v", err)
68+
}
69+
}
70+
}
71+
72+
func initStorage(storageType extensions.StorageType, bucket, region string) extensions.ObjectGetter {
73+
switch storageType {
74+
case extensions.StorageTypeS3:
75+
return extensions.NewS3(region, bucket)
76+
default:
77+
log.Fatalf("unknown storage type: %s", os.Getenv("STORAGE_TYPE"))
78+
}
79+
80+
return nil
81+
}

0 commit comments

Comments
 (0)