github.com/zntrio/harp/v2@v2.0.9/pkg/bundle/container.go (about) 1 // Licensed to Elasticsearch B.V. under one or more contributor 2 // license agreements. See the NOTICE file distributed with 3 // this work for additional information regarding copyright 4 // ownership. Elasticsearch B.V. licenses this file to you under 5 // the Apache License, Version 2.0 (the "License"); you may 6 // not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, 12 // software distributed under the License is distributed on an 13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 // KIND, either express or implied. See the License for the 15 // specific language governing permissions and limitations 16 // under the License. 17 18 package bundle 19 20 import ( 21 "bytes" 22 "compress/gzip" 23 "fmt" 24 "io" 25 26 bundlev1 "github.com/zntrio/harp/v2/api/gen/go/harp/bundle/v1" 27 containerv1 "github.com/zntrio/harp/v2/api/gen/go/harp/container/v1" 28 "github.com/zntrio/harp/v2/pkg/container" 29 "github.com/zntrio/harp/v2/pkg/sdk/types" 30 ) 31 32 // Statistic hold bundle statistic information. 33 type Statistic struct { 34 PackageCount uint32 35 CSOCompliantPackageNameCount uint32 36 SecretCount uint32 37 } 38 39 const ( 40 bundleContentType = "application/vnd.harp.v1.Bundle" 41 gzipCompressionLevel = 9 42 ) 43 44 // FromContainerReader returns a Bundle extracted from a secret container. 45 func FromContainerReader(r io.Reader) (*bundlev1.Bundle, error) { 46 // Check parameters 47 if types.IsNil(r) { 48 return nil, fmt.Errorf("unable to process nil reader") 49 } 50 51 // Load secret container 52 c, err := container.Load(r) 53 if err != nil { 54 return nil, fmt.Errorf("unable to load Bundle: %w", err) 55 } 56 57 // Delegate to bundle loader 58 return FromContainer(c) 59 } 60 61 // ToContainerWriter returns a Bundle packaged as a secret container. 62 func ToContainerWriter(w io.Writer, b *bundlev1.Bundle) error { 63 // Check parameters 64 if types.IsNil(w) { 65 return fmt.Errorf("unable to process nil writer") 66 } 67 if b == nil { 68 return fmt.Errorf("unable to process nil bundle") 69 } 70 71 // Create a container 72 c, err := ToContainer(b) 73 if err != nil { 74 return fmt.Errorf("unable to wrap bundle as a container: %w", err) 75 } 76 77 // Prepare secret container 78 return container.Dump(w, c) 79 } 80 81 // FromContainer unwraps a Bundle from a secret container. 82 func FromContainer(c *containerv1.Container) (*bundlev1.Bundle, error) { 83 // Check parameters 84 if types.IsNil(c) { 85 return nil, fmt.Errorf("unable to process nil container") 86 } 87 88 // Check headers 89 if types.IsNil(c.Headers) { 90 return nil, fmt.Errorf("unable to process nil container headers") 91 } 92 if c.Headers.ContentType != bundleContentType { 93 return nil, fmt.Errorf("invalid content type for Bundle loader") 94 } 95 if c.Headers.ContentEncoding != "gzip" { 96 return nil, fmt.Errorf("invalid content encoding for Bundle loader") 97 } 98 99 // Decompress bundle 100 zr, err := gzip.NewReader(bytes.NewReader(c.Raw)) 101 if err != nil { 102 return nil, fmt.Errorf("unable to initialize compression reader") 103 } 104 105 // Delegate to bundle loader 106 return Load(zr) 107 } 108 109 // ToContainer wrpas a Bundle as a container object. 110 func ToContainer(b *bundlev1.Bundle) (*containerv1.Container, error) { 111 if b == nil { 112 return nil, fmt.Errorf("unable to process nil bundle") 113 } 114 115 // Dump bundle 116 payload := &bytes.Buffer{} 117 118 // Compress with gzip 119 zw, errGz := gzip.NewWriterLevel(payload, gzipCompressionLevel) 120 if errGz != nil { 121 return nil, fmt.Errorf("unable to compress bundle content: %w", errGz) 122 } 123 124 // Delegate to Bundle Writer 125 if errDump := Dump(zw, b); errDump != nil { 126 return nil, fmt.Errorf("unable to dump container: %w", errDump) 127 } 128 129 // Close gzip writer 130 if errGz = zw.Close(); errGz != nil { 131 return nil, fmt.Errorf("unable to close compression writer: %w", errGz) 132 } 133 134 // Return container 135 return &containerv1.Container{ 136 Headers: &containerv1.Header{ 137 ContentEncoding: "gzip", 138 ContentType: bundleContentType, 139 }, 140 Raw: payload.Bytes(), 141 }, nil 142 }