code: func (p *Controller) Prepare(ctx context.Context) (err error) {
  	p.logger.Debug("Prepare")
  
  	remote, err := reference.ParseNormalizedNamed(p.spec.Remote)
  	if err != nil {
  		return errors.Wrapf(err, "error parsing remote reference %q", p.spec.Remote)
  	}
  
  	if p.spec.Name == "" {
  		p.spec.Name = remote.String()
  	}
  
  	var authConfig enginetypes.AuthConfig
  	privs := convertPrivileges(p.spec.Privileges)
  
  	pl, err := p.backend.Get(p.spec.Name)
  
  	defer func() {
  		if pl != nil && err == nil {
  			pl.Acquire()
  		}
  	}()
  
  	if err == nil && pl != nil {
  		if pl.SwarmServiceID != p.serviceID {
  			return errors.Errorf("plugin already exists: %s", p.spec.Name)
  		}
  		if pl.IsEnabled() {
  			if err := p.backend.Disable(pl.GetID(), &enginetypes.PluginDisableConfig{ForceDisable: true}); err != nil {
  				p.logger.WithError(err).Debug("could not disable plugin before running upgrade")
  			}
  		}
  		p.pluginID = pl.GetID()
  		return p.backend.Upgrade(ctx, remote, p.spec.Name, nil, &authConfig, privs, ioutil.Discard)
  	}
  
  	if err := p.backend.Pull(ctx, remote, p.spec.Name, nil, &authConfig, privs, ioutil.Discard, plugin.WithSwarmService(p.serviceID)); err != nil {
  		return err
  	}
  	pl, err = p.backend.Get(p.spec.Name)
  	if err != nil {
  		return err
  	}
  	p.pluginID = pl.GetID()
  
  	return nil
  }
docs: // Prepare is the prepare phase from swarmkit