Skip to content

Commit 2e52f13

Browse files
committed
updates
1 parent c90e73a commit 2e52f13

File tree

4 files changed

+103
-44
lines changed

4 files changed

+103
-44
lines changed

config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2720,6 +2720,10 @@ spec:
27202720
description: MajorVersion represents the major version of the running
27212721
pgAdmin.
27222722
type: integer
2723+
minorVersion:
2724+
description: MinorVersion represents the minor version of the running
2725+
pgAdmin.
2726+
type: string
27232727
observedGeneration:
27242728
description: observedGeneration represents the .metadata.generation
27252729
on which the status was based.

internal/controller/standalone_pgadmin/users.go

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -79,40 +79,55 @@ func (r *PGAdminReconciler) reconcilePGAdminUsers(ctx context.Context, pgadmin *
7979
return nil
8080
}
8181

82-
// If the pgAdmin version is not in the status or the image SHA has changed, get
83-
// the pgAdmin version and store it in the status.
84-
var pgadminVersion int
85-
if pgadmin.Status.MajorVersion == 0 || pgadmin.Status.ImageSHA != pgAdminImageSha {
86-
pgadminVersion, err = r.reconcilePGAdminMajorVersion(ctx, podExecutor)
82+
// If the pgAdmin major or minor version is not in the status or the image
83+
// SHA has changed, get the pgAdmin version and store it in the status.
84+
var pgadminMajorVersion int
85+
if pgadmin.Status.MajorVersion == 0 || pgadmin.Status.MinorVersion == "" ||
86+
pgadmin.Status.ImageSHA != pgAdminImageSha {
87+
88+
pgadminMinorVersion, err := r.reconcilePGAdminVersion(ctx, podExecutor)
8789
if err != nil {
8890
return err
8991
}
90-
pgadmin.Status.MajorVersion = pgadminVersion
92+
93+
// ensure minor version is valid before storing in status
94+
parsedMinorVersion, err := strconv.ParseFloat(pgadminMinorVersion, 64)
95+
if err != nil {
96+
return err
97+
}
98+
99+
// Note: "When converting a floating-point number to an integer, the
100+
// fraction is discarded (truncation towards zero)."
101+
// - https://go.dev/ref/spec#Conversions
102+
pgadminMajorVersion = int(parsedMinorVersion)
103+
104+
pgadmin.Status.MinorVersion = pgadminMinorVersion
105+
pgadmin.Status.MajorVersion = pgadminMajorVersion
91106
pgadmin.Status.ImageSHA = pgAdminImageSha
92107
} else {
93-
pgadminVersion = pgadmin.Status.MajorVersion
108+
pgadminMajorVersion = pgadmin.Status.MajorVersion
94109
}
95110

96111
// If the pgAdmin version is not v8 or higher, return early as user management is
97112
// only supported for pgAdmin v8 and higher.
98-
if pgadminVersion < 8 {
113+
if pgadminMajorVersion < 8 {
99114
// If pgAdmin version is less than v8 and user management is being attempted,
100115
// log a message clarifying that it is only supported for pgAdmin v8 and higher.
101116
if len(pgadmin.Spec.Users) > 0 {
102117
log.Info("User management is only supported for pgAdmin v8 and higher.",
103-
"pgadminVersion", pgadminVersion)
118+
"pgadminVersion", pgadminMajorVersion)
104119
}
105120
return err
106121
}
107122

108123
return r.writePGAdminUsers(ctx, pgadmin, podExecutor)
109124
}
110125

111-
// reconcilePGAdminMajorVersion execs into the pgAdmin pod and retrieves the pgAdmin major version
112-
func (r *PGAdminReconciler) reconcilePGAdminMajorVersion(ctx context.Context, exec Executor) (int, error) {
126+
// reconcilePGAdminVersion execs into the pgAdmin pod and retrieves the pgAdmin minor version
127+
func (r *PGAdminReconciler) reconcilePGAdminVersion(ctx context.Context, exec Executor) (string, error) {
113128
script := fmt.Sprintf(`
114129
PGADMIN_DIR=%s
115-
cd $PGADMIN_DIR && python3 -c "import config; print(config.APP_RELEASE)"
130+
cd $PGADMIN_DIR && python3 -c "import config; print(config.APP_VERSION)"
116131
`, pgAdminDir)
117132

118133
var stdin, stdout, stderr bytes.Buffer
@@ -121,10 +136,10 @@ cd $PGADMIN_DIR && python3 -c "import config; print(config.APP_RELEASE)"
121136
[]string{"bash", "-ceu", "--", script}...)
122137

123138
if err != nil {
124-
return 0, err
139+
return "", err
125140
}
126141

127-
return strconv.Atoi(strings.TrimSpace(stdout.String()))
142+
return strings.TrimSpace(stdout.String()), nil
128143
}
129144

130145
// writePGAdminUsers takes the users in the pgAdmin spec and writes (adds or updates) their data
@@ -170,11 +185,23 @@ cd $PGADMIN_DIR
170185
for _, user := range existingUsersArr {
171186
existingUsersMap[user.Username] = user
172187
}
188+
189+
var olderThan9_3 bool
190+
versionFloat, err := strconv.ParseFloat(pgadmin.Status.MinorVersion, 32)
191+
if err != nil {
192+
return err
193+
}
194+
if versionFloat < 9.3 {
195+
olderThan9_3 = true
196+
}
197+
173198
intentUsers := []pgAdminUserForJson{}
174199
for _, user := range pgadmin.Spec.Users {
175200
var stdin, stdout, stderr bytes.Buffer
176-
// typeFlag := "--nonadmin"
177201
typeFlag := "--role User"
202+
if olderThan9_3 {
203+
typeFlag = "--nonadmin"
204+
}
178205
isAdmin := false
179206
if user.Role == "Administrator" {
180207
typeFlag = "--admin"

internal/controller/standalone_pgadmin/users_test.go

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,16 @@ func TestReconcilePGAdminUsers(t *testing.T) {
110110
assert.Equal(t, namespace, pgadmin.Namespace)
111111
assert.Equal(t, container, naming.ContainerPGAdmin)
112112

113-
// Simulate a v7 version of pgAdmin by setting stdout to "7" for
114-
// podexec call in reconcilePGAdminMajorVersion
115-
_, _ = stdout.Write([]byte("7"))
113+
// Simulate a v7.1 version of pgAdmin by setting stdout to "7.1"
114+
// for podexec call in reconcilePGAdminVersion
115+
_, _ = stdout.Write([]byte("7.1"))
116116
return nil
117117
}
118118

119119
assert.NilError(t, r.reconcilePGAdminUsers(ctx, pgadmin))
120120
assert.Equal(t, calls, 1, "PodExec should be called once")
121121
assert.Equal(t, pgadmin.Status.MajorVersion, 7)
122+
assert.Equal(t, pgadmin.Status.MinorVersion, "7.1")
122123
assert.Equal(t, pgadmin.Status.ImageSHA, "fakeSHA")
123124
})
124125

@@ -145,20 +146,58 @@ func TestReconcilePGAdminUsers(t *testing.T) {
145146
) error {
146147
calls++
147148

148-
// Simulate a v7 version of pgAdmin by setting stdout to "7" for
149-
// podexec call in reconcilePGAdminMajorVersion
150-
_, _ = stdout.Write([]byte("7"))
149+
// Simulate a v7.1 version of pgAdmin by setting stdout to "7.1"
150+
// for podexec call in reconcilePGAdminVersion
151+
_, _ = stdout.Write([]byte("7.1"))
151152
return nil
152153
}
153154

154155
assert.NilError(t, r.reconcilePGAdminUsers(ctx, pgadmin))
155156
assert.Equal(t, calls, 1, "PodExec should be called once")
156157
assert.Equal(t, pgadmin.Status.MajorVersion, 7)
158+
assert.Equal(t, pgadmin.Status.MinorVersion, "7.1")
157159
assert.Equal(t, pgadmin.Status.ImageSHA, "newFakeSHA")
158160
})
161+
162+
t.Run("PodHealthyBadVersion", func(t *testing.T) {
163+
pgadmin := pgadmin.DeepCopy()
164+
pod := pod.DeepCopy()
165+
166+
pod.DeletionTimestamp = nil
167+
pod.Status.ContainerStatuses =
168+
[]corev1.ContainerStatus{{Name: naming.ContainerPGAdmin}}
169+
pod.Status.ContainerStatuses[0].State.Running =
170+
new(corev1.ContainerStateRunning)
171+
pod.Status.ContainerStatuses[0].ImageID = "fakeSHA"
172+
173+
r := new(PGAdminReconciler)
174+
r.Reader = fake.NewClientBuilder().WithObjects(pod).Build()
175+
176+
calls := 0
177+
r.PodExec = func(
178+
ctx context.Context, namespace, pod, container string,
179+
stdin io.Reader, stdout, stderr io.Writer, command ...string,
180+
) error {
181+
calls++
182+
183+
assert.Equal(t, pod, "pgadmin-123-0")
184+
assert.Equal(t, namespace, pgadmin.Namespace)
185+
assert.Equal(t, container, naming.ContainerPGAdmin)
186+
187+
// set expected version to something completely wrong
188+
_, _ = stdout.Write([]byte("woot"))
189+
return nil
190+
}
191+
192+
assert.ErrorContains(t, r.reconcilePGAdminUsers(ctx, pgadmin), "strconv.ParseFloat: parsing \"woot\": invalid syntax")
193+
assert.Equal(t, calls, 1, "PodExec should be called once")
194+
assert.Equal(t, pgadmin.Status.MajorVersion, 0)
195+
assert.Equal(t, pgadmin.Status.MinorVersion, "")
196+
assert.Equal(t, pgadmin.Status.ImageSHA, "")
197+
})
159198
}
160199

161-
func TestReconcilePGAdminMajorVersion(t *testing.T) {
200+
func TestReconcilePGAdminVersion(t *testing.T) {
162201
ctx := context.Background()
163202
pod := corev1.Pod{}
164203
pod.Namespace = "test-namespace"
@@ -180,30 +219,15 @@ func TestReconcilePGAdminMajorVersion(t *testing.T) {
180219
assert.Equal(t, namespace, "test-namespace")
181220
assert.Equal(t, container, naming.ContainerPGAdmin)
182221

183-
// Simulate a v7 version of pgAdmin by setting stdout to "7" for
184-
// podexec call in reconcilePGAdminMajorVersion
185-
_, _ = stdout.Write([]byte("7"))
222+
// Simulate a v9.3 version of pgAdmin by setting stdout to "9.3"
223+
// for podexec call in reconcilePGAdminVersion
224+
_, _ = stdout.Write([]byte("9.3"))
186225
return nil
187226
}
188227

189-
version, err := reconciler.reconcilePGAdminMajorVersion(ctx, podExecutor)
228+
version, err := reconciler.reconcilePGAdminVersion(ctx, podExecutor)
190229
assert.NilError(t, err)
191-
assert.Equal(t, version, 7)
192-
})
193-
194-
t.Run("FailedRetrieval", func(t *testing.T) {
195-
reconciler.PodExec = func(
196-
ctx context.Context, namespace, pod, container string,
197-
stdin io.Reader, stdout, stderr io.Writer, command ...string,
198-
) error {
199-
// Simulate the python call giving bad data (not a version int)
200-
_, _ = stdout.Write([]byte("asdfjkl;"))
201-
return nil
202-
}
203-
204-
version, err := reconciler.reconcilePGAdminMajorVersion(ctx, podExecutor)
205-
assert.Check(t, err != nil)
206-
assert.Equal(t, version, 0)
230+
assert.Equal(t, version, "9.3")
207231
})
208232

209233
t.Run("PodExecError", func(t *testing.T) {
@@ -214,9 +238,9 @@ func TestReconcilePGAdminMajorVersion(t *testing.T) {
214238
return errors.New("PodExecError")
215239
}
216240

217-
version, err := reconciler.reconcilePGAdminMajorVersion(ctx, podExecutor)
241+
version, err := reconciler.reconcilePGAdminVersion(ctx, podExecutor)
218242
assert.Check(t, err != nil)
219-
assert.Equal(t, version, 0)
243+
assert.Equal(t, version, "")
220244
})
221245
}
222246

pkg/apis/postgres-operator.crunchydata.com/v1beta1/standalone_pgadmin_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ type PGAdminStatus struct {
231231
// +optional
232232
MajorVersion int `json:"majorVersion,omitempty"`
233233

234+
// MinorVersion represents the minor version of the running pgAdmin.
235+
// +optional
236+
MinorVersion string `json:"minorVersion,omitempty"`
237+
234238
// observedGeneration represents the .metadata.generation on which the status was based.
235239
// +optional
236240
// +kubebuilder:validation:Minimum=0

0 commit comments

Comments
 (0)