Commit 4344b272 authored by Andrew Newdigate's avatar Andrew Newdigate

Docker sanity

parent 3b72b949
FROM ubuntu:14.04
ENV MONGO_MAJOR 3.0
ENV MONGO_VERSION 3.0.9
ENV REDIS_VERSION 3.0.6
ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-3.0.6.tar.gz
ENV REDIS_DOWNLOAD_SHA1 4b1c7b1201984bca8f7f9c6c58862f6928cf0a25
RUN apt-get install -y --no-install-recommends ca-certificates curl apt-transport-https
RUN curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -
RUN echo 'deb https://deb.nodesource.com/node_0.10 trusty main' > /etc/apt/sources.list.d/nodesource.list
RUN echo 'deb-src https://deb.nodesource.com/node_0.10 trusty main' >> /etc/apt/sources.list.d/nodesource.list
# gpg: key 7F0CEB10: public key "Richard Kreuter <richard@10gen.com>" imported
RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys 492EAFE8CD016A07919F1D2B9ECBEC467F0CEB10
RUN echo "deb http://repo.mongodb.org/apt/debian wheezy/mongodb-org/$MONGO_MAJOR main" > /etc/apt/sources.list.d/mongodb-org.list
RUN apt-get update
RUN apt-get install -y supervisor gcc libc6-dev make nodejs git build-essential \
mongodb-org=$MONGO_VERSION \
mongodb-org-server=$MONGO_VERSION \
mongodb-org-shell=$MONGO_VERSION \
mongodb-org-mongos=$MONGO_VERSION \
mongodb-org-tools=$MONGO_VERSION
# for redis-sentinel see: http://redis.io/topics/sentinel
RUN mkdir -p /usr/src/redis \
&& curl -sSL "$REDIS_DOWNLOAD_URL" -o redis.tar.gz \
&& echo "$REDIS_DOWNLOAD_SHA1 *redis.tar.gz" | sha1sum -c - \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& rm redis.tar.gz \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -r /usr/src/redis
RUN rm -rf /var/lib/apt/lists/*
COPY scripts/docker-test-env/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
RUN mkdir -p /data/db/1
RUN mkdir -p /data/db/2
COPY scripts/docker-test-env/sentinel.conf /etc/sentinel.conf
COPY scripts/docker-test-env/run-with-supervisor /usr/bin/run-with-supervisor
COPY scripts/docker-test-env/setup-gitter-webapp-test-env /usr/bin/setup-gitter-webapp-test-env
RUN npm install -g npm@latest-2
RUN npm install -g node-gyp
RUN mkdir /src
WORKDIR /src
#COPY package.json package.json
#COPY npm-shrinkwrap.json npm-shrinkwrap.json
#COPY modules/ modules/
#COPY shared/ shared/
#RUN sed 's#http://beta-internal:4873/#http://10.0.0.140:4873/#g' -ibak npm-shrinkwrap.json
#RUN npm install --registry http://10.0.0.140:4873/
COPY . .
ENTRYPOINT ["/usr/bin/run-with-supervisor"]
FROM node:0.10.38
RUN npm install -g npm
RUN npm install -g nodemon
RUN npm install -g node-gyp
RUN mkdir /src
WORKDIR /src
COPY package.json package.json
COPY npm-shrinkwrap.json npm-shrinkwrap.json
COPY modules/ modules/
COPY shared/ shared/
RUN sed 's#http://beta-internal:4873/#http://10.0.0.140:4873/#g' -ibak npm-shrinkwrap.json
RUN npm install --registry http://10.0.0.140:4873/
COPY . .
# Horrible hack for now
CMD ["node", "web"]
FROM node:4
RUN npm install -g node-gyp
RUN apt-get install comerr-dev
RUN mkdir /src
WORKDIR /src
COPY package.json package.json
COPY npm-shrinkwrap.json npm-shrinkwrap.json
COPY modules/ modules/
COPY shared/ shared/
RUN sed 's#http://beta-internal:4873/#http://10.0.0.140:4873/#g' -ibak npm-shrinkwrap.json
RUN npm install --registry http://10.0.0.140:4873/
COPY . .
# Horrible hack for now
CMD ["node", "web"]
#
# Redis
#
redis1:
image: redis:3.0.3
restart: always
hostname: redis1
ports:
- "6379:6379"
entrypoint: [ "/usr/local/bin/redis-server", "--bind", "0.0.0.0", "--port", "6379", "--maxclients", "200"]
redis2:
image: redis:3.0.3
restart: always
hostname: redis2
ports:
- "6380:6380"
links:
- redis1
entrypoint: [ "/usr/local/bin/redis-server", "--bind", "0.0.0.0", "--port", "6380", "--slaveof", "redis1", "6379", "--maxclients", "200"]
sentinel1:
image: redis:3.0.3
restart: 'on-failure:5'
hostname: sentinel1
links:
- redis1
- redis2
ports:
- "26379:26379"
entrypoint:
- /bin/bash
- -c
- |
echo 'sentinel monitor gitter-master-dev redis1 6379 1' > /redis-sentinel.conf &&
exec /usr/local/bin/redis-server /redis-sentinel.conf --sentinel --bind 0.0.0.0 --maxclients 200
#
# Mongo
#
mongo1:
hostname: mongo1
image: mongo:3.0
restart: always
ports:
- 27017:27017
links:
- mongo2
- mongo3
entrypoint: [ "/usr/bin/mongod", "--replSet", "troupeSet", "--journal", "--smallfiles", "--storageEngine=wiredTiger", "--oplogSize=20", "--port=27017" ]
mongo2:
hostname: mongo2
image: mongo:3.0
restart: always
ports:
- 27018:27018
entrypoint: [ "/usr/bin/mongod", "--replSet", "troupeSet", "--journal", "--smallfiles", "--storageEngine=wiredTiger", "--oplogSize=20", "--port=27018" ]
mongo3:
hostname: mongo3
image: mongo:3.0
restart: always
ports:
- 27019:27019
entrypoint: [ "/usr/bin/mongod", "--replSet", "troupeSet", "--journal", "--smallfiles", "--storageEngine=wiredTiger", "--oplogSize=20", "--port=27019" ]
mongosetup:
image: mongo:3.0
restart: 'no'
links:
- mongo1
- mongo2
- mongo3
volumes:
- ${WORKSPACE}:/src
environment:
ANNOUNCE_MONGO1_HOST: mongo1
ANNOUNCE_MONGO2_HOST: mongo2
ANNOUNCE_MONGO3_HOST: mongo3
RESOLVE_IPS: 1
working_dir: /src
entrypoint: [ "/src/scripts/docker/mongo/mongo-setup.sh" ]
neo4j:
image: kbastani/docker-neo4j
restart: always
ports:
- 7474:7474
elasticsearch:
image: elasticsearch:1.4.2
ports:
- 9200:9200
- 9300:9300
links:
- mongo1:mongo1
- mongo2:mongo2
- mongo3:mongo3
volumes:
- ${WORKSPACE}:/src
environment:
ANNOUNCE_ES_HOST:
working_dir: /src
entrypoint: [ "/src/scripts/docker/es/start-elasticsearch.sh" ]
elasticsearchsetup:
image: node:0.10
restart: 'no'
links:
- mongo1:mongo1
- mongo2:mongo2
- mongo3:mongo3
- elasticsearch:elasticsearch
volumes:
- ${WORKSPACE}:/src
working_dir: /src
entrypoint: [ "/src/scripts/docker/es/setup-elasticsearch.sh" ]
internal-min:
image: node:0.10
restart: 'no'
links:
- redis1
- redis2
- mongo1:gitter-mongo-dev
- mongo2
- mongo3
- sentinel1:gitter-redis-dev
volumes:
- ${WORKSPACE}:/src
working_dir: /src
internal:
image: node:0.10
restart: 'no'
links:
- redis1
- redis2
- neo4j:gitter-neo4j-dev
- mongo1:gitter-mongo-dev
- mongo2
- mongo3
- elasticsearch:gitter-es-dev
- sentinel1:gitter-redis-dev
volumes:
- ${WORKSPACE}:/src
working_dir: /src
# TODO: make this into an image
mongo1:
build: config/docker-tests/mongo
redistest1:
image: redis:3.0.3
restart: 'always'
entrypoint: [ "/usr/local/bin/redis-server", "--bind", "0.0.0.0", "--port", "6379", "--maxclients", "200"]
redistest2:
image: redis:3.0.3
restart: 'always'
links:
- redistest1
entrypoint: [ "/usr/local/bin/redis-server", "--bind", "0.0.0.0", "--port", "6380", "--slaveof", "redistest1", "6379", "--maxclients", "200"]
sentineltest1:
build: config/docker-tests/sentinel
restart: 'always'
links:
- redistest1
- redistest2
test:
image: node:0.10
links:
- mongo1
- redistest1
- redistest2
- sentineltest1
- mongo1:gitter-mongo-dev
- sentineltest1:gitter-redis-dev
extra_hosts:
- "beta-internal:10.0.0.140"
volumes:
- ${WORKSPACE}:/src
working_dir: /src
environment:
SKIP_BADGER_TESTS: 1
WORKSPACE: ${WORKSPACE}
DEBUG: ${DEBUG}
mongo1:
build: config/docker-tests/mongo
redistest1:
image: redis:3.0.3
restart: 'always'
entrypoint: [ "/usr/local/bin/redis-server", "--bind", "0.0.0.0", "--port", "6379", "--maxclients", "200"]
redistest2:
image: redis:3.0.3
restart: 'always'
links:
- redistest1
entrypoint: [ "/usr/local/bin/redis-server", "--bind", "0.0.0.0", "--port", "6380", "--slaveof", "redistest1", "6379", "--maxclients", "200"]
sentineltest1:
build: config/docker-tests/sentinel
restart: 'always'
links:
- redistest1
- redistest2
test:
build: .
links:
- mongo1
- redistest1
- redistest2
- sentineltest1
extra_hosts:
- "beta-internal:10.0.0.140"
environment:
SKIP_BADGER_TESTS: 1
entrypoint: [ "./node_modules/.bin/gulp", "test-docker"]
test-node4:
build: .
dockerfile: Dockerfile-node4
links:
- mongo1
- redistest1
- sentineltest1
extra_hosts:
- "beta-internal:10.0.0.140"
environment:
SKIP_BADGER_TESTS: 1
entrypoint: [ "./node_modules/.bin/gulp", "test-docker"]
#
# Redis
#
redis1:
image: redis:3.0.3
restart: 'always'
restart: always
hostname: redis1
ports:
- "6379:6379"
......@@ -8,16 +11,15 @@ redis1:
redis2:
image: redis:3.0.3
restart: 'always'
restart: always
hostname: redis2
ports:
- "6380:6380"
links:
- redis1
env_file:
- ./config/docker/redis-slave.env
entrypoint: [ "/bin/bash", "-c", "exec /usr/local/bin/redis-server --bind 0.0.0.0 --port 6380 --slaveof $$REDIS_MASTER_IP 6379 --maxclients 200"]
extra_hosts:
- gitter-redis-dev:${DOCKER_HOST_IP}
entrypoint: [ "/usr/local/bin/redis-server", "--bind", "0.0.0.0", "--port", "6380", "--slaveof", "gitter-redis-dev", "6379", "--maxclients", "200"]
sentinel1:
image: redis:3.0.3
......@@ -28,52 +30,59 @@ sentinel1:
- redis2
ports:
- "26379:26379"
env_file:
- ./config/docker/sentinel.env
entrypoint: [ "/bin/bash", "-c", "echo $$SENTINEL_CONF > /redis-sentinel.conf && exec /usr/local/bin/redis-server /redis-sentinel.conf --sentinel --bind 0.0.0.0 --maxclients 200"]
extra_hosts:
- gitter-redis-dev:${DOCKER_HOST_IP}
entrypoint: [ "/bin/bash", "-c", "echo 'sentinel monitor gitter-master-dev gitter-redis-dev 6379 1' > /redis-sentinel.conf && exec /usr/local/bin/redis-server /redis-sentinel.conf --sentinel --bind 0.0.0.0 --maxclients 200"]
#
# Mongo
#
mongo2:
hostname: mongo2
image: mongo:3.0
restart: 'always'
entrypoint: [ "/usr/bin/mongod", "--replSet", "troupeSet", "--journal", "--smallfiles", "--storageEngine=wiredTiger", "--oplogSize=20" ]
restart: always
entrypoint: [ "/usr/bin/mongod", "--replSet", "troupeSet", "--journal", "--smallfiles", "--storageEngine=wiredTiger", "--oplogSize=20", "--port=27018" ]
ports:
- "27018:27017"
- "27018:27018"
mongo3:
hostname: mongo3
image: mongo:3.0
restart: 'always'
entrypoint: [ "/usr/bin/mongod", "--replSet", "troupeSet", "--journal", "--smallfiles", "--storageEngine=wiredTiger", "--oplogSize=20" ]
restart: always
entrypoint: [ "/usr/bin/mongod", "--replSet", "troupeSet", "--journal", "--smallfiles", "--storageEngine=wiredTiger", "--oplogSize=20", "--port=27019" ]
ports:
- "27019:27017"
- "27019:27019"
mongo1:
hostname: mongo1
image: mongo:3.0
restart: 'always'
restart: always
entrypoint: [ "/usr/bin/mongod", "--replSet", "troupeSet", "--journal", "--smallfiles", "--storageEngine=wiredTiger", "--oplogSize=20" ]
ports:
- "27017:27017"
links:
- mongo2:mongo2
- mongo3:mongo3
- mongo2
- mongo3
mongosetup:
image: mongo:3.0
restart: 'no'
links:
- mongo1:mongo1
- mongo2:mongo2
- mongo3:mongo3
- mongo1
- mongo2
- mongo3
volumes:
- ./config/mongo-docker:/mongo-docker
- ./scripts:/scripts
entrypoint: [ "/bin/bash", "/mongo-docker/init-mongo.sh" ]
- ${WORKSPACE}:/src
environment:
ANNOUNCE_MONGO1_HOST: ${DOCKER_HOST_IP}
ANNOUNCE_MONGO2_HOST: ${DOCKER_HOST_IP}
ANNOUNCE_MONGO3_HOST: ${DOCKER_HOST_IP}
working_dir: /src
entrypoint: [ "/src/scripts/docker/mongo/mongo-setup.sh" ]
neo4j:
image: kbastani/docker-neo4j
restart: 'always'
restart: always
ports:
- "7474:7474"
......@@ -85,44 +94,25 @@ elasticsearch:
- "9200:9200"
- "9300:9300"
links:
- mongo1:mongo1
- mongo2:mongo2
- mongo3:mongo3
- mongo1
- mongo2
- mongo3
volumes:
- ./scripts:/scripts
env_file:
- ./config/docker/elasticsearch.env
entrypoint: [ "/scripts/elasticsearch/docker-elasticsearch.sh" ]
- ${WORKSPACE}:/src
environment:
ANNOUNCE_ES_HOST: ${DOCKER_HOST_IP}
working_dir: /src
entrypoint: [ "/src/scripts/docker/es/start-elasticsearch.sh" ]
elasticsearchsetup:
image: node:0.10.39
image: node:0.10
restart: 'no'
links:
- mongo1:mongo1
- mongo2:mongo2
- mongo3:mongo3
- mongo1
- mongo2
- mongo3
- elasticsearch:elasticsearch
volumes:
- ./scripts:/scripts
entrypoint: [ "/scripts/elasticsearch/setup-docker-elasticsearch.sh" ]
# For when we want to run the app in docker in future
# app:
# build: .
# links:
# - mongo1
# - mongo2
# - mongo3
# - redis1
# - redis2
# - sentinel1
# - elasticsearch:gitter-es-dev
# - neo4j:gitter-neo4j-dev
# extra_hosts:
# - "gitter-redis-dev:192.168.99.100"
# - "gitter-mongo-dev:192.168.99.100"
# ports:
# - "5000:5000"
# environment:
# DEBUG: "gitter:*"
# entrypoint: [ "node", "web" ]
- ${WORKSPACE}:/src
working_dir: /src
entrypoint: [ "/src/scripts/docker/es/setup-elasticsearch.sh" ]
......@@ -10,13 +10,12 @@ export DEBUG
echo $WORKSPACE
ISOLATED_UNIQ_ID=${BUILD_NUMBER:-$(date +"%Y-%m-%dT%H:%M:%S")}
JOB=${TEST_JOB-test}
function finish {
docker-compose -p "webapp-${ISOLATED_UNIQ_ID}" -f docker-compose.jenkins.yml stop
docker-compose -p "webapp-${ISOLATED_UNIQ_ID}" -f docker-compose.jenkins.yml rm -f
docker-compose -p "webapp-${ISOLATED_UNIQ_ID}" -f docker-compose.internal.yml stop
docker-compose -p "webapp-${ISOLATED_UNIQ_ID}" -f docker-compose.internal.yml rm -f
}
trap finish EXIT
docker-compose -p "webapp-${ISOLATED_UNIQ_ID}" -f docker-compose.jenkins.yml build mongo1 sentineltest1 "${JOB}"
docker-compose -p "webapp-${ISOLATED_UNIQ_ID}" -f docker-compose.jenkins.yml run --entrypoint "$(join ' ' "$@")" "${JOB}"
docker-compose -p "webapp-${ISOLATED_UNIQ_ID}" -f docker-compose.internal.yml run -d mongosetup
docker-compose -p "webapp-${ISOLATED_UNIQ_ID}" -f docker-compose.internal.yml run --rm --entrypoint "$(join ' ' "$@")" internal-min
......@@ -10,4 +10,4 @@ function finish {
trap finish EXIT
docker-compose -p "webapp-${ISOLATED_UNIQ_ID}" -f docker-compose.test.yml build mongo1 sentineltest1 "${JOB}"
docker-compose -p "webapp-${ISOLATED_UNIQ_ID}" -f docker-compose.test.yml run "${JOB}"
docker-compose -p "webapp-${ISOLATED_UNIQ_ID}" -f docker-compose.test.yml run --rm "${JOB}"
FROM ubuntu:14.04
ENV MONGO_MAJOR 3.0
ENV MONGO_VERSION 3.0.9
ENV REDIS_VERSION 3.0.6
ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-3.0.6.tar.gz
ENV REDIS_DOWNLOAD_SHA1 4b1c7b1201984bca8f7f9c6c58862f6928cf0a25
RUN apt-get install -y --no-install-recommends ca-certificates curl apt-transport-https
RUN curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -
RUN echo 'deb https://deb.nodesource.com/node_0.10 trusty main' > /etc/apt/sources.list.d/nodesource.list
RUN echo 'deb-src https://deb.nodesource.com/node_0.10 trusty main' >> /etc/apt/sources.list.d/nodesource.list
# gpg: key 7F0CEB10: public key "Richard Kreuter <richard@10gen.com>" imported
RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys 492EAFE8CD016A07919F1D2B9ECBEC467F0CEB10
RUN echo "deb http://repo.mongodb.org/apt/debian wheezy/mongodb-org/$MONGO_MAJOR main" > /etc/apt/sources.list.d/mongodb-org.list
RUN apt-get update
RUN apt-get install -y supervisor gcc libc6-dev make nodejs git build-essential \
mongodb-org=$MONGO_VERSION \
mongodb-org-server=$MONGO_VERSION \
mongodb-org-shell=$MONGO_VERSION \
mongodb-org-mongos=$MONGO_VERSION \
mongodb-org-tools=$MONGO_VERSION
# for redis-sentinel see: http://redis.io/topics/sentinel
RUN mkdir -p /usr/src/redis \
&& curl -sSL "$REDIS_DOWNLOAD_URL" -o redis.tar.gz \
&& echo "$REDIS_DOWNLOAD_SHA1 *redis.tar.gz" | sha1sum -c - \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& rm redis.tar.gz \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -r /usr/src/redis
RUN rm -rf /var/lib/apt/lists/*
COPY ./supervisord.conf /etc/supervisor/conf.d/supervisord.conf
RUN mkdir -p /data/db/1
RUN mkdir -p /data/db/2
COPY ./sentinel.conf /etc/sentinel.conf
COPY ./run-with-supervisor /usr/bin/run-with-supervisor
COPY ./setup-gitter-webapp-test-env /usr/bin/setup-gitter-webapp-test-env
ENTRYPOINT ["/usr/bin/run-with-supervisor"]
#!/bin/bash
/usr/bin/supervisord &
$@
kill %1
sentinel monitor gitter-master-dev 127.0.0.1 6379 1
sentinel down-after-milliseconds gitter-master-dev 5000
sentinel failover-timeout gitter-master-dev 30000
sentinel config-epoch gitter-master-dev 3
port 26379
#!/bin/bash
set -e
set -x
while [[ "$(mongo --quiet --eval 'db.serverStatus().ok') || echo 0" = "0" ]]; do
echo Waiting for replicaset to come online
sleep 1
done
if [[ "$(mongo --quiet --eval 'rs.status().ok')" != "1" ]]; then
echo Replicaset not initialised. Initialising
mongo <<-DELIM
rs.initiate({_id: 'troupeSet', members: [
                         {_id: 0, host: 'localhost:27017', priority: 2 },
                         {_id: 1, host: 'localhost:27018', priority: 1 }]
});
DELIM
mongo --eval 'printjson(rs.status())';
while [[ "$(mongo --quiet --eval 'rs.status().myState')" != "1" ]]; do
echo Waiting for replicaset to come online
mongo --eval 'printjson(rs.status())';
sleep 1
done
fi
mongo --eval 'printjson(rs.status())';
mongo gitter <<"DELIM"
db.oauthclients.update(
{ clientKey: 'web-internal' },
{ clientKey: 'web-internal',
clientSecret: 'x',
name: 'Web Client',
tag: 'web-app',
}, true /* upsert */);
db.oauthclients.update(
{ clientKey: '1' },
{
clientKey: '1',
clientSecret: '***REMOVED***',
name: 'Gitter OSX',
tag: 'mac',
registeredRedirectUri: 'https://gitter.im/login/oauth/callback',
canSkipAuthorization: true
},
true /* upsert */);
db.oauthclients.update(
{ clientKey: '2' },
{
clientKey: '2',
clientSecret: '***REMOVED***',
name: 'Gitter Beta OSX',
tag: 'mac-beta',
registeredRedirectUri: 'https://gitter.im/login/oauth/callback',
canSkipAuthorization: true
},
true /* upsert */);
db.oauthclients.update(
{ clientKey: '3' },
{
clientKey: '3',
clientSecret: '***REMOVED***',
name: 'Troupe Notifier Mac',
tag: 'mac-notifier',
registeredRedirectUri: 'https://gitter.im/login/oauth/callback',
canSkipAuthorization: true
},
true /* upsert */);
db.oauthclients.update(
{ clientKey: '4' },
{
clientKey: '4',
clientSecret: '***REMOVED***',
name: 'Troupe Notifier Mac Beta',
tag: 'mac-notifier-beta',
registeredRedirectUri: 'https://gitter.im/login/oauth/callback',
canSkipAuthorization: true
},
true /* upsert */);
db.oauthclients.update(
{ clientKey: '5' },
{
clientKey: '5',
clientSecret: '***REMOVED***',
name: 'Troupe for Windows Beta',
tag: 'windows-notifier-beta',
registeredRedirectUri: 'https://gitter.im/login/oauth/callback',
canSkipAuthorization: true
},
true /* upsert */);
db.oauthclients.update(
{ clientKey: '6' },
{
clientKey: '6',
clientSecret: '***REMOVED***',
name: 'Troupe for Windows',
tag: 'windows-notifier',
registeredRedirectUri: 'https://gitter.im/login/oauth/callback',
canSkipAuthorization: true
},
true /* upsert */);
/* iOS */
db.oauthclients.update(
{ clientKey: 'ios-beta-dev' },
{
clientKey: 'ios-beta-dev',
clientSecret: 'apwX2tugtqTQUWJfQCkxCo6wyR2QxH',
name: 'Gitter iOS App',
tag: 'ios-beta-dev',
registeredRedirectUri: 'https://gitter.im/login/oauth/callback',
canSkipAuthorization: true
},
true /* upsert */);
db.oauthclients.update(