| 290 | } |
| 291 | |
| 292 | func buildDockerArchive(configJSON []byte, configDigest digest.Digest, layerContent []byte, layerDigest digest.Digest, prefix string) (io.ReadCloser, error) { |
| 293 | layerFileName := layerDigest.Encoded() + ".tar.gz" |
| 294 | configFileName := configDigest.Encoded() + ".json" |
| 295 | |
| 296 | var repoTags []string |
| 297 | if parsed, err := referenceutil.Parse(prefix); err == nil && parsed.String() != "" { |
| 298 | repoTags = []string{parsed.String()} |
| 299 | } |
| 300 | |
| 301 | dockerManifest := []struct { |
| 302 | Config string `json:"Config"` |
| 303 | RepoTags []string `json:"RepoTags,omitempty"` |
| 304 | Layers []string `json:"Layers"` |
| 305 | }{{ |
| 306 | Config: configFileName, |
| 307 | RepoTags: repoTags, |
| 308 | Layers: []string{layerFileName}, |
| 309 | }} |
| 310 | |
| 311 | dockerManifestJSON, err := json.Marshal(dockerManifest) |
| 312 | if err != nil { |
| 313 | return nil, err |
| 314 | } |
| 315 | |
| 316 | buf := &bytes.Buffer{} |
| 317 | tw := tar.NewWriter(buf) |
| 318 | |
| 319 | files := []struct { |
| 320 | name string |
| 321 | content []byte |
| 322 | }{ |
| 323 | {"manifest.json", dockerManifestJSON}, |
| 324 | {configFileName, configJSON}, |
| 325 | {layerFileName, layerContent}, |
| 326 | } |
| 327 | |
| 328 | for _, f := range files { |
| 329 | if err := tw.WriteHeader(&tar.Header{ |
| 330 | Name: f.name, |
| 331 | Mode: 0644, |
| 332 | Size: int64(len(f.content)), |
| 333 | }); err != nil { |
| 334 | return nil, err |
| 335 | } |
| 336 | if _, err := tw.Write(f.content); err != nil { |
| 337 | return nil, err |
| 338 | } |
| 339 | } |
| 340 | |
| 341 | if err := tw.Close(); err != nil { |
| 342 | return nil, err |
| 343 | } |
| 344 | |
| 345 | return io.NopCloser(buf), nil |
| 346 | } |
| 347 | |
| 348 | func randomRef(prefix string) string { |
| 349 | var b [6]byte |