github.com/Racer159/jackal@v0.32.7-0.20240401174413-0bd2339e4f2e/src/test/e2e/51_oci_compose_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: 2021-Present The Jackal Authors 3 4 // Package test provides e2e tests for Jackal. 5 package test 6 7 import ( 8 "fmt" 9 "os" 10 "path/filepath" 11 "strconv" 12 "strings" 13 "testing" 14 15 "github.com/Racer159/jackal/src/pkg/layout" 16 "github.com/Racer159/jackal/src/pkg/transform" 17 "github.com/Racer159/jackal/src/pkg/utils" 18 "github.com/Racer159/jackal/src/types" 19 "github.com/defenseunicorns/pkg/helpers" 20 "github.com/stretchr/testify/require" 21 "github.com/stretchr/testify/suite" 22 corev1 "k8s.io/api/core/v1" 23 "oras.land/oras-go/v2/registry" 24 ) 25 26 type SkeletonSuite struct { 27 suite.Suite 28 *require.Assertions 29 Reference registry.Reference 30 } 31 32 var ( 33 importEverything = filepath.Join("src", "test", "packages", "51-import-everything") 34 importEverythingPath string 35 importception = filepath.Join("src", "test", "packages", "51-import-everything", "inception") 36 importceptionPath string 37 ) 38 39 func (suite *SkeletonSuite) SetupSuite() { 40 suite.Assertions = require.New(suite.T()) 41 42 e2e.SetupDockerRegistry(suite.T(), 555) 43 suite.Reference.Registry = "localhost:555" 44 45 // Setup the package paths after e2e has been initialized 46 importEverythingPath = filepath.Join("build", fmt.Sprintf("jackal-package-import-everything-%s-0.0.1.tar.zst", e2e.Arch)) 47 importceptionPath = filepath.Join("build", fmt.Sprintf("jackal-package-importception-%s-0.0.1.tar.zst", e2e.Arch)) 48 } 49 50 func (suite *SkeletonSuite) TearDownSuite() { 51 e2e.TeardownRegistry(suite.T(), 555) 52 53 err := os.RemoveAll(filepath.Join("src", "test", "packages", "51-import-everything", "charts", "local")) 54 suite.NoError(err) 55 err = os.RemoveAll(importEverythingPath) 56 suite.NoError(err) 57 err = os.RemoveAll(importceptionPath) 58 suite.NoError(err) 59 } 60 61 func (suite *SkeletonSuite) Test_0_Publish_Skeletons() { 62 suite.T().Log("E2E: Skeleton Package Publish oci://") 63 ref := suite.Reference.String() 64 65 helmCharts := filepath.Join("examples", "helm-charts") 66 _, stdErr, err := e2e.Jackal("package", "publish", helmCharts, "oci://"+ref, "--insecure") 67 suite.NoError(err) 68 suite.Contains(stdErr, "Published "+ref) 69 70 bigBang := filepath.Join("src", "test", "packages", "51-import-everything", "big-bang-min") 71 _, stdErr, err = e2e.Jackal("package", "publish", bigBang, "oci://"+ref, "--insecure") 72 suite.NoError(err) 73 suite.Contains(stdErr, "Published "+ref) 74 75 composable := filepath.Join("src", "test", "packages", "09-composable-packages") 76 _, stdErr, err = e2e.Jackal("package", "publish", composable, "oci://"+ref, "--insecure") 77 suite.NoError(err) 78 suite.Contains(stdErr, "Published "+ref) 79 80 _, stdErr, err = e2e.Jackal("package", "publish", importEverything, "oci://"+ref, "--insecure") 81 suite.NoError(err) 82 suite.Contains(stdErr, "Published "+ref) 83 84 _, _, err = e2e.Jackal("package", "inspect", "oci://"+ref+"/import-everything:0.0.1", "--insecure", "-a", "skeleton") 85 suite.NoError(err) 86 87 _, _, err = e2e.Jackal("package", "pull", "oci://"+ref+"/import-everything:0.0.1", "-o", "build", "--insecure", "-a", "skeleton") 88 suite.NoError(err) 89 90 _, _, err = e2e.Jackal("package", "pull", "oci://"+ref+"/helm-charts:0.0.1", "-o", "build", "--insecure", "-a", "skeleton") 91 suite.NoError(err) 92 93 _, _, err = e2e.Jackal("package", "pull", "oci://"+ref+"/big-bang-min:2.10.0", "-o", "build", "--insecure", "-a", "skeleton") 94 suite.NoError(err) 95 96 _, _, err = e2e.Jackal("package", "pull", "oci://"+ref+"/test-compose-package:0.0.1", "-o", "build", "--insecure", "-a", "skeleton") 97 suite.NoError(err) 98 } 99 100 func (suite *SkeletonSuite) Test_1_Compose_Everything_Inception() { 101 suite.T().Log("E2E: Skeleton Package Compose oci://") 102 103 _, _, err := e2e.Jackal("package", "create", importEverything, "-o", "build", "--insecure", "--confirm") 104 suite.NoError(err) 105 106 _, _, err = e2e.Jackal("package", "create", importception, "-o", "build", "--insecure", "--confirm") 107 suite.NoError(err) 108 109 _, stdErr, err := e2e.Jackal("package", "inspect", importEverythingPath) 110 suite.NoError(err) 111 112 targets := []string{ 113 "import-component-local == import-component-local", 114 "import-component-oci == import-component-oci", 115 "import-big-bang == import-big-bang", 116 "file-imports == file-imports", 117 "local-chart-import == local-chart-import", 118 } 119 120 for _, target := range targets { 121 suite.Contains(stdErr, target) 122 } 123 } 124 125 func (suite *SkeletonSuite) Test_2_FilePaths() { 126 suite.T().Log("E2E: Skeleton + Package File Paths") 127 128 pkgTars := []string{ 129 filepath.Join("build", fmt.Sprintf("jackal-package-import-everything-%s-0.0.1.tar.zst", e2e.Arch)), 130 filepath.Join("build", "jackal-package-import-everything-skeleton-0.0.1.tar.zst"), 131 filepath.Join("build", fmt.Sprintf("jackal-package-importception-%s-0.0.1.tar.zst", e2e.Arch)), 132 filepath.Join("build", "jackal-package-helm-charts-skeleton-0.0.1.tar.zst"), 133 filepath.Join("build", "jackal-package-big-bang-min-skeleton-2.10.0.tar.zst"), 134 filepath.Join("build", "jackal-package-test-compose-package-skeleton-0.0.1.tar.zst"), 135 } 136 137 for _, pkgTar := range pkgTars { 138 var pkg types.JackalPackage 139 140 unpacked := strings.TrimSuffix(pkgTar, ".tar.zst") 141 defer os.RemoveAll(unpacked) 142 defer os.RemoveAll(pkgTar) 143 _, _, err := e2e.Jackal("tools", "archiver", "decompress", pkgTar, unpacked, "--unarchive-all") 144 suite.NoError(err) 145 suite.DirExists(unpacked) 146 147 // Verify skeleton contains kustomize-generated manifests. 148 if strings.HasSuffix(pkgTar, "jackal-package-test-compose-package-skeleton-0.0.1.tar.zst") { 149 kustomizeGeneratedManifests := []string{ 150 "kustomization-connect-service-0.yaml", 151 "kustomization-connect-service-1.yaml", 152 "kustomization-connect-service-two-0.yaml", 153 } 154 manifestDir := filepath.Join(unpacked, "components", "test-compose-package", "manifests") 155 for _, manifest := range kustomizeGeneratedManifests { 156 manifestPath := filepath.Join(manifestDir, manifest) 157 suite.FileExists(manifestPath, "expected to find kustomize-generated manifest: %q", manifestPath) 158 var configMap corev1.ConfigMap 159 err := utils.ReadYaml(manifestPath, &configMap) 160 suite.NoError(err) 161 suite.Equal("ConfigMap", configMap.Kind, "expected manifest %q to be of kind ConfigMap", manifestPath) 162 } 163 } 164 165 err = utils.ReadYaml(filepath.Join(unpacked, layout.JackalYAML), &pkg) 166 suite.NoError(err) 167 suite.NotNil(pkg) 168 169 components := pkg.Components 170 suite.NotNil(components) 171 172 isSkeleton := false 173 if strings.Contains(pkgTar, "-skeleton-") { 174 isSkeleton = true 175 } 176 suite.verifyComponentPaths(unpacked, components, isSkeleton) 177 } 178 } 179 180 func (suite *SkeletonSuite) DirOrFileExists(path string) { 181 invalid := helpers.InvalidPath(path) 182 suite.Falsef(invalid, "path specified does not exist: %s", path) 183 } 184 185 func (suite *SkeletonSuite) verifyComponentPaths(unpackedPath string, components []types.JackalComponent, isSkeleton bool) { 186 187 if isSkeleton { 188 suite.NoDirExists(filepath.Join(unpackedPath, "images")) 189 suite.NoDirExists(filepath.Join(unpackedPath, "sboms")) 190 } 191 192 for _, component := range components { 193 if len(component.Charts) == 0 && len(component.Files) == 0 && len(component.Manifests) == 0 && len(component.DataInjections) == 0 && len(component.Repos) == 0 { 194 // component has no files to check 195 continue 196 } 197 198 base := filepath.Join(unpackedPath, "components", component.Name) 199 componentPaths := layout.ComponentPaths{ 200 Base: base, 201 Temp: filepath.Join(base, layout.TempDir), 202 Files: filepath.Join(base, layout.FilesDir), 203 Charts: filepath.Join(base, layout.ChartsDir), 204 Repos: filepath.Join(base, layout.ReposDir), 205 Manifests: filepath.Join(base, layout.ManifestsDir), 206 DataInjections: filepath.Join(base, layout.DataInjectionsDir), 207 Values: filepath.Join(base, layout.ValuesDir), 208 } 209 210 if isSkeleton && component.DeprecatedCosignKeyPath != "" { 211 suite.FileExists(filepath.Join(base, component.DeprecatedCosignKeyPath)) 212 } 213 214 if isSkeleton && component.Extensions.BigBang != nil { 215 for _, valuesFile := range component.Extensions.BigBang.ValuesFiles { 216 suite.FileExists(filepath.Join(base, valuesFile)) 217 } 218 } 219 220 for chartIdx, chart := range component.Charts { 221 if isSkeleton && chart.URL != "" { 222 continue 223 } else if isSkeleton { 224 dir := fmt.Sprintf("%s-%d", chart.Name, chartIdx) 225 suite.DirExists(filepath.Join(componentPaths.Charts, dir)) 226 continue 227 } 228 tgz := fmt.Sprintf("%s-%s.tgz", chart.Name, chart.Version) 229 suite.FileExists(filepath.Join(componentPaths.Charts, tgz)) 230 } 231 232 for filesIdx, file := range component.Files { 233 if isSkeleton && helpers.IsURL(file.Source) { 234 continue 235 } else if isSkeleton { 236 suite.FileExists(filepath.Join(base, file.Source)) 237 continue 238 } 239 path := filepath.Join(componentPaths.Files, strconv.Itoa(filesIdx), filepath.Base(file.Target)) 240 suite.DirOrFileExists(path) 241 } 242 243 for dataIdx, data := range component.DataInjections { 244 if isSkeleton && helpers.IsURL(data.Source) { 245 continue 246 } else if isSkeleton { 247 suite.DirOrFileExists(filepath.Join(base, data.Source)) 248 continue 249 } 250 path := filepath.Join(componentPaths.DataInjections, strconv.Itoa(dataIdx), filepath.Base(data.Target.Path)) 251 suite.DirOrFileExists(path) 252 } 253 254 for _, manifest := range component.Manifests { 255 if isSkeleton { 256 suite.Nil(manifest.Kustomizations) 257 } 258 for filesIdx, path := range manifest.Files { 259 if isSkeleton && helpers.IsURL(path) { 260 continue 261 } else if isSkeleton { 262 suite.FileExists(filepath.Join(base, path)) 263 continue 264 } 265 suite.FileExists(filepath.Join(componentPaths.Manifests, fmt.Sprintf("%s-%d.yaml", manifest.Name, filesIdx))) 266 } 267 for kustomizeIdx := range manifest.Kustomizations { 268 path := filepath.Join(componentPaths.Manifests, fmt.Sprintf("kustomization-%s-%d.yaml", manifest.Name, kustomizeIdx)) 269 suite.FileExists(path) 270 } 271 } 272 273 if !isSkeleton { 274 for _, repo := range component.Repos { 275 dir, err := transform.GitURLtoFolderName(repo) 276 suite.NoError(err) 277 suite.DirExists(filepath.Join(componentPaths.Repos, dir)) 278 } 279 } 280 } 281 282 } 283 284 func TestSkeletonSuite(t *testing.T) { 285 e2e.SetupWithCluster(t) 286 287 suite.Run(t, new(SkeletonSuite)) 288 }