docs: function RegistryClientV2(opts) {
      var self = this;
      assert.object(opts, 'opts');
      // One of `opts.name` or `opts.repo`.
      assert.ok((opts.name || opts.repo) && !(opts.name && opts.repo),
          'exactly one of opts.name or opts.repo must be given');
      if (opts.name) {
          assert.string(opts.name, 'opts.name');
      } else {
          assert.object(opts.repo, 'opts.repo');
      }
      assert.optionalObject(opts.log, 'opts.log');
      assert.optionalString(opts.username, 'opts.username');
      if (opts.username) {
          assert.string(opts.password,
              'opts.password required if username given');
      } else {
          assert.optionalString(opts.password, 'opts.password');
      }
      assert.optionalString(opts.token, 'opts.token');  // for Bearer auth
      assert.optionalBool(opts.insecure, 'opts.insecure');
      assert.optionalString(opts.scheme, 'opts.scheme');
      assert.optionalBool(opts.acceptManifestLists, 'opts.acceptManifestLists');
      assert.optionalNumber(opts.maxSchemaVersion, 'opts.maxSchemaVersion');
      // TODO: options to control the trust db for CA verification
      // TODO add passing through other restify options: userAgent, ...
      // Restify/Node HTTP client options.
      assert.optionalBool(opts.agent, 'opts.agent');
      assert.optionalString(opts.userAgent, 'opts.userAgent');
  
      this.log = _createLogger(opts.log);
  
      this.insecure = Boolean(opts.insecure);
      if (opts.name) {
          this.repo = common.parseRepo(opts.name);
      } else {
          this.repo = common.deepObjCopy(opts.repo);
      }
      if (opts.scheme) {
          this.repo.index.scheme = opts.scheme;
      } else if (!this.repo.index.scheme &&
          common.isLocalhost(this.repo.index.name))
      {
          // Per docker.git:registry/config.go#NewServiceConfig we special
          // case localhost to allow HTTP. Note that this lib doesn't do
          // the "try HTTPS, then fallback to HTTP if allowed" thing that
          // Docker-docker does, we'll just prefer HTTP for localhost.
          this.repo.index.scheme = 'http';
      }
  
      this.acceptManifestLists = opts.acceptManifestLists || false;
      this.maxSchemaVersion = opts.maxSchemaVersion || 1;
      this.username = opts.username;
      this.password = opts.password;
      this._loggedIn = false;
      this._loggedInScope = null; // Keeps track of the login type.
      this._authInfo = null;
      this._headers = {};
  
      _setAuthHeaderFromAuthInfo(this._headers, {
          token: opts.token,
          username: opts.username,
          password: opts.password
      });
  
      // XXX relevant for v2?
      //this._cookieJar = new tough.CookieJar();
  
      if (this.repo.index.official) {  // v1
          this._url = DEFAULT_V2_REGISTRY;
      } else {
          this._url = common.urlFromIndex(this.repo.index);
      }
      this.log.trace({url: this._url}, 'RegistryClientV2 url');
  
      this._commonHttpClientOpts = {
          log: this.log,
          agent: opts.agent,
          proxy: opts.proxy,
          rejectUnauthorized: !this.insecure,
          userAgent: opts.userAgent || common.DEFAULT_USERAGENT
      };
      this._clientsToClose = [];
  
      Object.defineProperty(this, '_api', {
          get: function () {
              if (self.__api === undefined) {
                  self.__api = new DockerJsonClient(common.objMerge({
                      url: self._url
                  }, self._commonHttpClientOpts));
                  self._clientsToClose.push(self.__api);
              }
              return this.__api;
          }
      });
  
      Object.defineProperty(this, '_httpapi', {
          get: function () {
              if (self.__httpapi === undefined) {
                  self.__httpapi = new restifyClients.HttpClient(common.objMerge({
                      url: self._url
                  }, self._commonHttpClientOpts));
                  self._clientsToClose.push(self.__httpapi);
              }
              return this.__httpapi;
          }
      });
  }