github.com/khulnasoft/cli@v0.0.0-20240402070845-01bcad7beefa/cli/context/store/store_test.go (about) 1 // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: 2 //go:build go1.19 3 4 package store 5 6 import ( 7 "archive/tar" 8 "archive/zip" 9 "bufio" 10 "bytes" 11 "crypto/rand" 12 "encoding/json" 13 "fmt" 14 "io" 15 "os" 16 "path" 17 "path/filepath" 18 "testing" 19 20 "github.com/docker/docker/errdefs" 21 "gotest.tools/v3/assert" 22 is "gotest.tools/v3/assert/cmp" 23 ) 24 25 type endpoint struct { 26 Foo string `json:"a_very_recognizable_field_name"` 27 } 28 29 type context struct { 30 Bar string `json:"another_very_recognizable_field_name"` 31 } 32 33 var testCfg = NewConfig(func() any { return &context{} }, 34 EndpointTypeGetter("ep1", func() any { return &endpoint{} }), 35 EndpointTypeGetter("ep2", func() any { return &endpoint{} }), 36 ) 37 38 func TestExportImport(t *testing.T) { 39 s := New(t.TempDir(), testCfg) 40 err := s.CreateOrUpdate( 41 Metadata{ 42 Endpoints: map[string]any{ 43 "ep1": endpoint{Foo: "bar"}, 44 }, 45 Metadata: context{Bar: "baz"}, 46 Name: "source", 47 }) 48 assert.NilError(t, err) 49 file1 := make([]byte, 1500) 50 rand.Read(file1) 51 file2 := make([]byte, 3700) 52 rand.Read(file2) 53 err = s.ResetEndpointTLSMaterial("source", "ep1", &EndpointTLSData{ 54 Files: map[string][]byte{ 55 "file1": file1, 56 "file2": file2, 57 }, 58 }) 59 assert.NilError(t, err) 60 r := Export("source", s) 61 defer r.Close() 62 err = Import("dest", s, r) 63 assert.NilError(t, err) 64 srcMeta, err := s.GetMetadata("source") 65 assert.NilError(t, err) 66 destMeta, err := s.GetMetadata("dest") 67 assert.NilError(t, err) 68 assert.DeepEqual(t, destMeta.Metadata, srcMeta.Metadata) 69 assert.DeepEqual(t, destMeta.Endpoints, srcMeta.Endpoints) 70 srcFileList, err := s.ListTLSFiles("source") 71 assert.NilError(t, err) 72 destFileList, err := s.ListTLSFiles("dest") 73 assert.NilError(t, err) 74 assert.Equal(t, 1, len(destFileList)) 75 assert.Equal(t, 1, len(srcFileList)) 76 assert.Equal(t, 2, len(destFileList["ep1"])) 77 assert.Equal(t, 2, len(srcFileList["ep1"])) 78 srcData1, err := s.GetTLSData("source", "ep1", "file1") 79 assert.NilError(t, err) 80 assert.DeepEqual(t, file1, srcData1) 81 srcData2, err := s.GetTLSData("source", "ep1", "file2") 82 assert.NilError(t, err) 83 assert.DeepEqual(t, file2, srcData2) 84 destData1, err := s.GetTLSData("dest", "ep1", "file1") 85 assert.NilError(t, err) 86 assert.DeepEqual(t, file1, destData1) 87 destData2, err := s.GetTLSData("dest", "ep1", "file2") 88 assert.NilError(t, err) 89 assert.DeepEqual(t, file2, destData2) 90 } 91 92 func TestRemove(t *testing.T) { 93 s := New(t.TempDir(), testCfg) 94 err := s.CreateOrUpdate( 95 Metadata{ 96 Endpoints: map[string]any{ 97 "ep1": endpoint{Foo: "bar"}, 98 }, 99 Metadata: context{Bar: "baz"}, 100 Name: "source", 101 }) 102 assert.NilError(t, err) 103 assert.NilError(t, s.ResetEndpointTLSMaterial("source", "ep1", &EndpointTLSData{ 104 Files: map[string][]byte{ 105 "file1": []byte("test-data"), 106 }, 107 })) 108 assert.NilError(t, s.Remove("source")) 109 _, err = s.GetMetadata("source") 110 assert.Check(t, is.ErrorType(err, errdefs.IsNotFound)) 111 f, err := s.ListTLSFiles("source") 112 assert.NilError(t, err) 113 assert.Equal(t, 0, len(f)) 114 } 115 116 func TestListEmptyStore(t *testing.T) { 117 result, err := New(t.TempDir(), testCfg).List() 118 assert.NilError(t, err) 119 assert.Check(t, len(result) == 0) 120 } 121 122 func TestErrHasCorrectContext(t *testing.T) { 123 _, err := New(t.TempDir(), testCfg).GetMetadata("no-exists") 124 assert.ErrorContains(t, err, "no-exists") 125 assert.Check(t, is.ErrorType(err, errdefs.IsNotFound)) 126 } 127 128 func TestDetectImportContentType(t *testing.T) { 129 buf := new(bytes.Buffer) 130 r := bufio.NewReader(buf) 131 ct, err := getImportContentType(r) 132 assert.NilError(t, err) 133 assert.Assert(t, zipType != ct) 134 } 135 136 func TestImportTarInvalid(t *testing.T) { 137 testDir := t.TempDir() 138 tf := path.Join(testDir, "test.context") 139 140 f, err := os.Create(tf) 141 assert.NilError(t, err) 142 defer f.Close() 143 144 tw := tar.NewWriter(f) 145 hdr := &tar.Header{ 146 Name: "dummy-file", 147 Mode: 0o600, 148 Size: int64(len("hello world")), 149 } 150 err = tw.WriteHeader(hdr) 151 assert.NilError(t, err) 152 _, err = tw.Write([]byte("hello world")) 153 assert.NilError(t, err) 154 err = tw.Close() 155 assert.NilError(t, err) 156 157 source, err := os.Open(tf) 158 assert.NilError(t, err) 159 defer source.Close() 160 var r io.Reader = source 161 s := New(testDir, testCfg) 162 err = Import("tarInvalid", s, r) 163 assert.ErrorContains(t, err, "unexpected context file") 164 } 165 166 func TestImportZip(t *testing.T) { 167 testDir := t.TempDir() 168 zf := path.Join(testDir, "test.zip") 169 170 f, err := os.Create(zf) 171 assert.NilError(t, err) 172 defer f.Close() 173 w := zip.NewWriter(f) 174 175 meta, err := json.Marshal(Metadata{ 176 Endpoints: map[string]any{ 177 "ep1": endpoint{Foo: "bar"}, 178 }, 179 Metadata: context{Bar: "baz"}, 180 Name: "source", 181 }) 182 assert.NilError(t, err) 183 files := []struct { 184 Name, Body string 185 }{ 186 {"meta.json", string(meta)}, 187 {path.Join("tls", "docker", "ca.pem"), string([]byte("ca.pem"))}, 188 } 189 190 for _, file := range files { 191 f, err := w.Create(file.Name) 192 assert.NilError(t, err) 193 _, err = f.Write([]byte(file.Body)) 194 assert.NilError(t, err) 195 } 196 197 err = w.Close() 198 assert.NilError(t, err) 199 200 source, err := os.Open(zf) 201 assert.NilError(t, err) 202 ct, err := getImportContentType(bufio.NewReader(source)) 203 assert.NilError(t, err) 204 assert.Equal(t, zipType, ct) 205 206 source, _ = os.Open(zf) 207 defer source.Close() 208 var r io.Reader = source 209 s := New(testDir, testCfg) 210 err = Import("zipTest", s, r) 211 assert.NilError(t, err) 212 } 213 214 func TestImportZipInvalid(t *testing.T) { 215 testDir := t.TempDir() 216 zf := path.Join(testDir, "test.zip") 217 218 f, err := os.Create(zf) 219 assert.NilError(t, err) 220 defer f.Close() 221 w := zip.NewWriter(f) 222 223 df, err := w.Create("dummy-file") 224 assert.NilError(t, err) 225 _, err = df.Write([]byte("hello world")) 226 assert.NilError(t, err) 227 err = w.Close() 228 assert.NilError(t, err) 229 230 source, err := os.Open(zf) 231 assert.NilError(t, err) 232 defer source.Close() 233 var r io.Reader = source 234 s := New(testDir, testCfg) 235 err = Import("zipInvalid", s, r) 236 assert.ErrorContains(t, err, "unexpected context file") 237 } 238 239 func TestCorruptMetadata(t *testing.T) { 240 tempDir := t.TempDir() 241 s := New(tempDir, testCfg) 242 err := s.CreateOrUpdate( 243 Metadata{ 244 Endpoints: map[string]any{ 245 "ep1": endpoint{Foo: "bar"}, 246 }, 247 Metadata: context{Bar: "baz"}, 248 Name: "source", 249 }) 250 assert.NilError(t, err) 251 252 // Simulate the meta.json file getting corrupted 253 // by some external process. 254 contextDir := s.meta.contextDir(contextdirOf("source")) 255 contextFile := filepath.Join(contextDir, metaFile) 256 err = os.WriteFile(contextFile, nil, 0o600) 257 assert.NilError(t, err) 258 259 // Assert that the error message gives the user some clue where to look. 260 _, err = s.GetMetadata("source") 261 assert.ErrorContains(t, err, fmt.Sprintf("parsing %s: unexpected end of JSON input", contextFile)) 262 }