@@ -5,8 +5,14 @@ package e2e
55import (
66 "context"
77 "fmt"
8+ "os"
9+ "regexp"
10+ "strings"
811 "testing"
12+ "time"
913
14+ "github.com/docker/docker/api/types"
15+ "github.com/docker/docker/client"
1016 "github.com/kong/go-kong/kong"
1117 "github.com/kong/kubernetes-testing-framework/pkg/environments"
1218 "github.com/samber/lo"
@@ -15,6 +21,7 @@ import (
1521 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1622
1723 "github.com/kong/kubernetes-ingress-controller/v2/test/internal/helpers"
24+ "github.com/kong/kubernetes-ingress-controller/v2/test/internal/testenv"
1825)
1926
2027const (
@@ -103,12 +110,14 @@ func testManifestsUpgrade(
103110 oldManifest , err := httpClient .Get (testParams .fromManifestURL )
104111 require .NoError (t , err )
105112 defer oldManifest .Body .Close ()
113+ oldManifestPath := dumpToTempFile (t , oldManifest .Body )
114+
115+ skipIfNotTwoConsecutiveKongMinorVersions (t , oldManifestPath , testParams .toManifestPath )
106116
107117 t .Log ("configuring upgrade manifests test" )
108118 ctx , env := setupE2ETest (t )
109119
110120 t .Logf ("deploying previous kong manifests: %s" , testParams .fromManifestURL )
111- oldManifestPath := dumpToTempFile (t , oldManifest .Body )
112121 ManifestDeploy {
113122 Path : oldManifestPath ,
114123 SkipTestPatches : true ,
@@ -154,3 +163,80 @@ func testManifestsUpgrade(
154163
155164 verifyIngressWithEchoBackendsPath (ctx , t , env , numberOfEchoBackends , newPath )
156165}
166+
167+ // skipIfNotTwoConsecutiveKongMinorVersions skips the test if the old and new Kong versions are not two consecutive
168+ // minor versions. This is necessary because Kong in DB-mode doesn't support skipping minor versions when upgrading.
169+ // See the Gateway upgrade guide for details: https://docs.konghq.com/gateway/latest/upgrade/.
170+ func skipIfNotTwoConsecutiveKongMinorVersions (
171+ t * testing.T ,
172+ oldManifestPath string ,
173+ newManifestPath string ,
174+ ) {
175+ oldKongVersion := extractKongVersionFromManifest (t , oldManifestPath )
176+
177+ var newKongVersion kong.Version
178+ if targetKongImage := testenv .KongImageTag (); targetKongImage != "" {
179+ // If the target Kong image is specified via environment variable, use it...
180+ newKongVersion = extractKongVersionFromDockerImage (t , targetKongImage )
181+ } else {
182+ // ...otherwise, use the version used in the new manifest.
183+ newKongVersion = extractKongVersionFromManifest (t , newManifestPath )
184+ }
185+
186+ if oldKongVersion .Major () != newKongVersion .Major () ||
187+ oldKongVersion .Minor ()+ 1 != newKongVersion .Minor () {
188+ t .Skipf ("skipping upgrade test because the old and new Kong versions are not two consecutive minor versions: %s and %s" ,
189+ oldKongVersion , newKongVersion )
190+ }
191+ }
192+
193+ var kongVersionRegex = regexp .MustCompile (`image: (kong:.*)` )
194+
195+ // extractKongVersionFromManifest extracts the Kong version from the manifest.
196+ func extractKongVersionFromManifest (t * testing.T , manifestPath string ) kong.Version {
197+ manifest , err := os .ReadFile (manifestPath )
198+ require .NoError (t , err )
199+
200+ res := kongVersionRegex .FindStringSubmatch (string (manifest ))
201+ require .NotEmpty (t , res )
202+
203+ version := res [1 ]
204+ return extractKongVersionFromDockerImage (t , version )
205+ }
206+
207+ // extractKongVersionFromDockerImage extracts the Kong version from the docker image by inspecting the image's env vars
208+ // for the KONG_VERSION env var.
209+ func extractKongVersionFromDockerImage (t * testing.T , image string ) kong.Version {
210+ dockerc , err := client .NewClientWithOpts (client .FromEnv )
211+ require .NoError (t , err )
212+
213+ ctx := context .Background ()
214+
215+ t .Logf ("pulling docker image %s to inspect it" , image )
216+ _ , err = dockerc .ImagePull (ctx , image , types.ImagePullOptions {})
217+ require .NoError (t , err )
218+
219+ t .Logf ("inspecting docker image %s" , image )
220+ var imageDetails types.ImageInspect
221+ // Retry because the image may not be available immediately after pulling it.
222+ require .Eventually (t , func () bool {
223+ var err error
224+ imageDetails , _ , err = dockerc .ImageInspectWithRaw (ctx , image )
225+ if err != nil {
226+ t .Logf ("failed to inspect docker image %s: %s" , image , err )
227+ return false
228+ }
229+ return true
230+ }, time .Minute , time .Second )
231+
232+ kongVersionEnv , ok := lo .Find (imageDetails .Config .Env , func (s string ) bool {
233+ return strings .HasPrefix (s , "KONG_VERSION=" )
234+ })
235+ require .True (t , ok , "KONG_VERSION env var not found in image %s" , image )
236+
237+ version , err := kong .ParseSemanticVersion (strings .TrimPrefix (kongVersionEnv , "KONG_VERSION=" ))
238+ require .NoError (t , err )
239+ t .Logf ("parsed Kong version %s from docker image %s" , version , image )
240+
241+ return version
242+ }
0 commit comments