CreateFromContext creates a plugin from the given pluginDir which contains both the rootfs and the config.json and a repoName with optional tag.
(ctx context.Context, tarCtx io.ReadCloser, options *backend.PluginCreateConfig)
| 637 | // CreateFromContext creates a plugin from the given pluginDir which contains |
| 638 | // both the rootfs and the config.json and a repoName with optional tag. |
| 639 | func (pm *Manager) CreateFromContext(ctx context.Context, tarCtx io.ReadCloser, options *backend.PluginCreateConfig) (retErr error) { |
| 640 | pm.muGC.RLock() |
| 641 | defer pm.muGC.RUnlock() |
| 642 | |
| 643 | ref, err := reference.ParseNormalizedNamed(options.RepoName) |
| 644 | if err != nil { |
| 645 | return errors.Wrapf(err, "failed to parse reference %v", options.RepoName) |
| 646 | } |
| 647 | if _, ok := ref.(reference.Canonical); ok { |
| 648 | return errors.Errorf("canonical references are not permitted") |
| 649 | } |
| 650 | name := reference.FamiliarString(reference.TagNameOnly(ref)) |
| 651 | |
| 652 | if err := pm.config.Store.validateName(name); err != nil { // fast check, real check is in createPlugin() |
| 653 | return err |
| 654 | } |
| 655 | |
| 656 | tmpRootFSDir, err := os.MkdirTemp(pm.tmpDir(), ".rootfs") |
| 657 | if err != nil { |
| 658 | return errors.Wrap(err, "failed to create temp directory") |
| 659 | } |
| 660 | defer func() { |
| 661 | if err := os.RemoveAll(tmpRootFSDir); err != nil { |
| 662 | log.G(ctx).WithError(err).Warn("failed to remove temp rootfs directory") |
| 663 | } |
| 664 | }() |
| 665 | |
| 666 | var configJSON []byte |
| 667 | rootFS := splitConfigRootFSFromTar(tarCtx, &configJSON) |
| 668 | |
| 669 | rootFSBlob, err := pm.blobStore.Writer(ctx, content.WithRef(name)) |
| 670 | if err != nil { |
| 671 | return err |
| 672 | } |
| 673 | defer rootFSBlob.Close() |
| 674 | |
| 675 | gzw := gzip.NewWriter(rootFSBlob) |
| 676 | rootFSReader := io.TeeReader(rootFS, gzw) |
| 677 | |
| 678 | if err := chrootarchive.Untar(rootFSReader, tmpRootFSDir, nil); err != nil { |
| 679 | return err |
| 680 | } |
| 681 | if err := rootFS.Close(); err != nil { |
| 682 | return err |
| 683 | } |
| 684 | |
| 685 | if configJSON == nil { |
| 686 | return errors.New("config not found") |
| 687 | } |
| 688 | |
| 689 | if err := gzw.Close(); err != nil { |
| 690 | return errors.Wrap(err, "error closing gzip writer") |
| 691 | } |
| 692 | |
| 693 | var config plugin.Config |
| 694 | if err := json.Unmarshal(configJSON, &config); err != nil { |
| 695 | return errors.Wrap(err, "failed to parse config") |
| 696 | } |
no test coverage detected