docs: function login(opts, cb) {
      assert.object(opts, 'opts');
      assert.ok(opts.index || opts.indexName,
          'opts.index or opts.indexName is required');
      assert.string(opts.username, 'opts.username');
      assert.string(opts.email, 'opts.email');
      assert.string(opts.password, 'opts.password');
      assert.optionalBool(opts.insecure, 'opts.insecure');
      assert.optionalObject(opts.log, 'opts.log');
      assert.optionalString(opts.userAgent, 'opts.userAgent');
      assert.func(cb, 'cb');
  
      var index = opts.index || opts.indexName;
      if (typeof (index) === 'string') {
          try {
              index = common.parseIndex(index);
          } catch (indexNameErr) {
              cb(indexNameErr);
              return;
          }
      } else {
          assert.object(index, 'opts.index');
      }
      var indexUrl = common.urlFromIndex(index);
  
      var client = restifyClients.createJsonClient({
          url: indexUrl,
          log: opts.log,
          userAgent: opts.userAgent || common.DEFAULT_USERAGENT,
          agent: opts.agent,
          proxy: opts.proxy,
          headers: opts.headers,
          rejectUnauthorized: !opts.insecure,
          // Want to fail fast:
          retry: false,
          connectTimeout: 10000
      });
      var status;
  
      vasync.pipeline({arg: {}, funcs: [
          /*
           * This *can* create a user (e.g. on Docker Hub). Typically though the
           * statusCode is used to determine next steps.
           */
          function createUser(ctx, next) {
              client.post({
                  path: '/v1/users/'
              }, {
                  username: opts.username,
                  email: opts.email,
                  password: opts.password
              }, function _afterCreateUser(err, req, res, body) {
                  if (err && !res) {  // e.g. connect error
                      return next(err);
                  }
                  ctx.createStatusCode = res.statusCode;
                  ctx.createErr = err;
                  ctx.createBody = body;
                  next();
              });
          },
  
          function handle201(ctx, next) {
              if (ctx.createStatusCode !== 201) {
                  return next();
              }
              if (index.official) {
                  status = 'Account created. Please use the confirmation ' +
                      'link we sent to your e-mail to activate it.';
              } else {
                  status = 'Account created. Please see the documentation ' +
                      'of the registry ' + opts.indexName +
                      ' for instructions how to activate it.';
              }
              next(true);
          },
  
          function handle400(ctx, next) {
              if (ctx.createStatusCode !== 400) {
                  return next();
              }
              if (ctx.createBody !== 'Username or email already exists') {
                  return next(new Error(fmt('Registration: %j', ctx.createBody)));
              }
  
              client.basicAuth(opts.username, opts.password);
              client.get({
                  path: '/v1/users/'
              }, function (err, req, res, body) {
                  if (res.statusCode === 200) {
                      status = 'Login Succeeded';
                      next(true);
                  } else if (res.statusCode === 401) {
                      next(new Error('Wrong login/password, please try again'));
                  } else if (res.statusCode === 403) {
                      if (index.official) {
                          next(new Error('Login: Account is not Active. ' +
                              'Please check your e-mail for a confirmation ' +
                              'link.'));
                      } else {
                          next(new Error('Login: Account is not Active. ' +
                              'Please see the documentation of the registry ' +
                              opts.indexName + ' for instructions how to ' +
                              'activate it.'));
                      }
                  } else {
                      next(new Error(fmt('Login: %s (Code: %d; Headers: %j)',
                          body, res.statusCode, res.headers)));
                  }
              });
          },
  
          function handle401(ctx, next) {
              if (ctx.createStatusCode !== 401) {
                  return next();
              }
  
              client.basicAuth(opts.username, opts.password);
              client.get({
                  path: '/v1/users/'
              }, function (err, req, res, body) {
                  if (res.statusCode === 200) {
                      status = 'Login Succeeded';
                      next(true);
                  } else if (res.statusCode === 401) {
                      next(new Error('Wrong login/password, please try again'));
                  } else {
                      next(new Error(fmt('Login: %s (Code: %d; Headers: %j)',
                          body, res.statusCode, res.headers)));
                  }
              });
          },
  
          function handleOther(ctx, next) {
              var msg = fmt('Unexpected status code [%d] : %s',
                  ctx.createStatusCode, ctx.createBody);
              if (ctx.createErr) {
                  next(new VError(ctx.createErr, msg));
              } else {
                  next(new Error(msg));
              }
          }
  
      ]}, function (err) {
          if (err === true) { // Signal for early abort.
              err = null;
          }
          client.close();
          if (err) {
              cb(err);
          } else {
              cb(null, {status: status});
          }
      });
  }