fix: resolve CouchDB deployment and init job issues
- Remove problematic ERL_FLAGS from CouchDB StatefulSet - Copy setup-couchdb.js to backend/scripts/ for Docker image inclusion - Update init job to use full DNS name and add timeout/retry logic - Fix script path in init job command 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
472
backend/scripts/setup-couchdb.js
Normal file
472
backend/scripts/setup-couchdb.js
Normal file
@@ -0,0 +1,472 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
// Setup module path to include backend node_modules
|
||||||
|
const path = require('path');
|
||||||
|
const backendPath = path.join(__dirname, '..', 'backend');
|
||||||
|
process.env.NODE_PATH = path.join(backendPath, 'node_modules') + ':' + (process.env.NODE_PATH || '');
|
||||||
|
require('module').Module._initPaths();
|
||||||
|
|
||||||
|
const Nano = require('nano');
|
||||||
|
require('dotenv').config({ path: path.join(backendPath, '.env') });
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
const COUCHDB_URL = process.env.COUCHDB_URL || 'http://localhost:5984';
|
||||||
|
const COUCHDB_USER = process.env.COUCHDB_USER || 'admin';
|
||||||
|
const COUCHDB_PASSWORD = process.env.COUCHDB_PASSWORD || 'admin';
|
||||||
|
const COUCHDB_DB_NAME = process.env.COUCHDB_DB_NAME || 'adopt-a-street';
|
||||||
|
|
||||||
|
class CouchDBSetup {
|
||||||
|
constructor() {
|
||||||
|
this.nano = Nano({
|
||||||
|
url: COUCHDB_URL,
|
||||||
|
auth: { username: COUCHDB_USER, password: COUCHDB_PASSWORD }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async initialize() {
|
||||||
|
console.log('🚀 Initializing CouchDB setup...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Test connection
|
||||||
|
await this.nano.info();
|
||||||
|
console.log('✅ Connected to CouchDB');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Failed to connect to CouchDB:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async createDatabase() {
|
||||||
|
console.log(`📦 Creating database: ${COUCHDB_DB_NAME}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.nano.db.create(COUCHDB_DB_NAME);
|
||||||
|
console.log('✅ Database created successfully');
|
||||||
|
} catch (error) {
|
||||||
|
if (error.statusCode === 412) {
|
||||||
|
console.log('ℹ️ Database already exists');
|
||||||
|
} else {
|
||||||
|
console.error('❌ Failed to create database:', error.message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async createIndexes() {
|
||||||
|
console.log('🔍 Creating indexes...');
|
||||||
|
|
||||||
|
const db = this.nano.use(COUCHDB_DB_NAME);
|
||||||
|
|
||||||
|
// Create design document with indexes
|
||||||
|
const designDoc = {
|
||||||
|
_id: '_design/adopt-a-street',
|
||||||
|
views: {
|
||||||
|
users_by_email: {
|
||||||
|
map: "function(doc) { if (doc.type === 'user') { emit(doc.email, doc); } }"
|
||||||
|
},
|
||||||
|
streets_by_location: {
|
||||||
|
map: "function(doc) { if (doc.type === 'street') { emit(doc.location, doc); } }"
|
||||||
|
},
|
||||||
|
by_user: {
|
||||||
|
map: "function(doc) { if (doc.user && doc.user.userId) { emit(doc.user.userId, doc); } }"
|
||||||
|
},
|
||||||
|
users_by_points: {
|
||||||
|
map: "function(doc) { if (doc.type === 'user') { emit(doc.points, doc); } }"
|
||||||
|
},
|
||||||
|
posts_by_date: {
|
||||||
|
map: "function(doc) { if (doc.type === 'post') { emit(doc.createdAt, doc); } }"
|
||||||
|
},
|
||||||
|
streets_by_status: {
|
||||||
|
map: "function(doc) { if (doc.type === 'street') { emit(doc.status, doc); } }"
|
||||||
|
},
|
||||||
|
events_by_date_status: {
|
||||||
|
map: "function(doc) { if (doc.type === 'event') { emit([doc.date, doc.status], doc); } }"
|
||||||
|
},
|
||||||
|
comments_by_post: {
|
||||||
|
map: "function(doc) { if (doc.type === 'comment' && doc.post && doc.post.postId) { emit(doc.post.postId, doc); } }"
|
||||||
|
},
|
||||||
|
transactions_by_user_date: {
|
||||||
|
map: "function(doc) { if (doc.type === 'point_transaction' && doc.user && doc.user.userId) { emit([doc.user.userId, doc.createdAt], doc); } }"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
indexes: {
|
||||||
|
users_by_email: {
|
||||||
|
index: {
|
||||||
|
fields: ["type", "email"]
|
||||||
|
},
|
||||||
|
name: "user-by-email",
|
||||||
|
type: "json"
|
||||||
|
},
|
||||||
|
streets_by_location: {
|
||||||
|
index: {
|
||||||
|
fields: ["type", "location"]
|
||||||
|
},
|
||||||
|
name: "streets-by-location",
|
||||||
|
type: "json"
|
||||||
|
},
|
||||||
|
by_user: {
|
||||||
|
index: {
|
||||||
|
fields: ["type", "user.userId"]
|
||||||
|
},
|
||||||
|
name: "by-user",
|
||||||
|
type: "json"
|
||||||
|
},
|
||||||
|
users_by_points: {
|
||||||
|
index: {
|
||||||
|
fields: ["type", "points"]
|
||||||
|
},
|
||||||
|
name: "users-by-points",
|
||||||
|
type: "json"
|
||||||
|
},
|
||||||
|
posts_by_date: {
|
||||||
|
index: {
|
||||||
|
fields: ["type", "createdAt"]
|
||||||
|
},
|
||||||
|
name: "posts-by-date",
|
||||||
|
type: "json"
|
||||||
|
},
|
||||||
|
streets_by_status: {
|
||||||
|
index: {
|
||||||
|
fields: ["type", "status"]
|
||||||
|
},
|
||||||
|
name: "streets-by-status",
|
||||||
|
type: "json"
|
||||||
|
},
|
||||||
|
events_by_date_status: {
|
||||||
|
index: {
|
||||||
|
fields: ["type", "date", "status"]
|
||||||
|
},
|
||||||
|
name: "events-by-date-status",
|
||||||
|
type: "json"
|
||||||
|
},
|
||||||
|
comments_by_post: {
|
||||||
|
index: {
|
||||||
|
fields: ["type", "post.postId"]
|
||||||
|
},
|
||||||
|
name: "comments-by-post",
|
||||||
|
type: "json"
|
||||||
|
},
|
||||||
|
transactions_by_user_date: {
|
||||||
|
index: {
|
||||||
|
fields: ["type", "user.userId", "createdAt"]
|
||||||
|
},
|
||||||
|
name: "transactions-by-user-date",
|
||||||
|
type: "json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
language: "javascript"
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await db.insert(designDoc);
|
||||||
|
console.log('✅ Design document and indexes created successfully');
|
||||||
|
} catch (error) {
|
||||||
|
if (error.statusCode === 409) {
|
||||||
|
// Document already exists, update it
|
||||||
|
const existing = await db.get('_design/adopt-a-street');
|
||||||
|
designDoc._rev = existing._rev;
|
||||||
|
await db.insert(designDoc);
|
||||||
|
console.log('✅ Design document and indexes updated successfully');
|
||||||
|
} else {
|
||||||
|
console.error('❌ Failed to create indexes:', error.message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async createSecurityDocument() {
|
||||||
|
console.log('🔒 Setting up security document...');
|
||||||
|
|
||||||
|
const db = this.nano.use(COUCHDB_DB_NAME);
|
||||||
|
|
||||||
|
const securityDoc = {
|
||||||
|
admins: {
|
||||||
|
names: [COUCHDB_USER],
|
||||||
|
roles: []
|
||||||
|
},
|
||||||
|
members: {
|
||||||
|
names: [],
|
||||||
|
roles: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await db.insert(securityDoc, '_security');
|
||||||
|
console.log('✅ Security document created successfully');
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('⚠️ Failed to create security document:', error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async seedBadges() {
|
||||||
|
console.log('🏆 Seeding badges...');
|
||||||
|
|
||||||
|
const db = this.nano.use(COUCHDB_DB_NAME);
|
||||||
|
|
||||||
|
// Check if badges already exist
|
||||||
|
try {
|
||||||
|
const existingBadges = await db.find({
|
||||||
|
selector: { type: 'badge' },
|
||||||
|
limit: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existingBadges.docs.length > 0) {
|
||||||
|
console.log('ℹ️ Badges already exist, skipping seeding');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Continue with seeding
|
||||||
|
}
|
||||||
|
|
||||||
|
const badges = [
|
||||||
|
// Street Adoption Badges
|
||||||
|
{
|
||||||
|
_id: 'badge_first_adoption',
|
||||||
|
type: 'badge',
|
||||||
|
name: 'First Adoption',
|
||||||
|
description: 'Adopted your first street',
|
||||||
|
icon: '🏡',
|
||||||
|
criteria: { type: 'street_adoptions', threshold: 1 },
|
||||||
|
rarity: 'common',
|
||||||
|
order: 1,
|
||||||
|
isActive: true,
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
updatedAt: new Date().toISOString()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: 'badge_street_adopter',
|
||||||
|
type: 'badge',
|
||||||
|
name: 'Street Adopter',
|
||||||
|
description: 'Adopted 5 streets',
|
||||||
|
icon: '🏘️',
|
||||||
|
criteria: { type: 'street_adoptions', threshold: 5 },
|
||||||
|
rarity: 'rare',
|
||||||
|
order: 2,
|
||||||
|
isActive: true,
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
updatedAt: new Date().toISOString()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: 'badge_neighborhood_champion',
|
||||||
|
type: 'badge',
|
||||||
|
name: 'Neighborhood Champion',
|
||||||
|
description: 'Adopted 10 streets',
|
||||||
|
icon: '🌆',
|
||||||
|
criteria: { type: 'street_adoptions', threshold: 10 },
|
||||||
|
rarity: 'epic',
|
||||||
|
order: 3,
|
||||||
|
isActive: true,
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
updatedAt: new Date().toISOString()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: 'badge_city_guardian',
|
||||||
|
type: 'badge',
|
||||||
|
name: 'City Guardian',
|
||||||
|
description: 'Adopted 25 streets',
|
||||||
|
icon: '🏙️',
|
||||||
|
criteria: { type: 'street_adoptions', threshold: 25 },
|
||||||
|
rarity: 'legendary',
|
||||||
|
order: 4,
|
||||||
|
isActive: true,
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
updatedAt: new Date().toISOString()
|
||||||
|
},
|
||||||
|
// Task Completion Badges
|
||||||
|
{
|
||||||
|
_id: 'badge_first_task',
|
||||||
|
type: 'badge',
|
||||||
|
name: 'First Task',
|
||||||
|
description: 'Completed your first task',
|
||||||
|
icon: '✅',
|
||||||
|
criteria: { type: 'task_completions', threshold: 1 },
|
||||||
|
rarity: 'common',
|
||||||
|
order: 5,
|
||||||
|
isActive: true,
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
updatedAt: new Date().toISOString()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: 'badge_task_master',
|
||||||
|
type: 'badge',
|
||||||
|
name: 'Task Master',
|
||||||
|
description: 'Completed 10 tasks',
|
||||||
|
icon: '🎯',
|
||||||
|
criteria: { type: 'task_completions', threshold: 10 },
|
||||||
|
rarity: 'rare',
|
||||||
|
order: 6,
|
||||||
|
isActive: true,
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
updatedAt: new Date().toISOString()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: 'badge_dedicated_worker',
|
||||||
|
type: 'badge',
|
||||||
|
name: 'Dedicated Worker',
|
||||||
|
description: 'Completed 50 tasks',
|
||||||
|
icon: '🛠️',
|
||||||
|
criteria: { type: 'task_completions', threshold: 50 },
|
||||||
|
rarity: 'epic',
|
||||||
|
order: 7,
|
||||||
|
isActive: true,
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
updatedAt: new Date().toISOString()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: 'badge_maintenance_legend',
|
||||||
|
type: 'badge',
|
||||||
|
name: 'Maintenance Legend',
|
||||||
|
description: 'Completed 100 tasks',
|
||||||
|
icon: '⚡',
|
||||||
|
criteria: { type: 'task_completions', threshold: 100 },
|
||||||
|
rarity: 'legendary',
|
||||||
|
order: 8,
|
||||||
|
isActive: true,
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
updatedAt: new Date().toISOString()
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
try {
|
||||||
|
const results = await db.bulk({ docs: badges });
|
||||||
|
const successCount = results.filter(r => !r.error).length;
|
||||||
|
console.log(`✅ Successfully seeded ${successCount} badges`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Failed to seed badges:', error.message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async verifySetup() {
|
||||||
|
console.log('🔍 Verifying setup...');
|
||||||
|
|
||||||
|
const db = this.nano.use(COUCHDB_DB_NAME);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check database info
|
||||||
|
const info = await db.info();
|
||||||
|
console.log(`✅ Database "${info.db_name}" is ready`);
|
||||||
|
console.log(` - Doc count: ${info.doc_count}`);
|
||||||
|
console.log(` - Update seq: ${info.update_seq}`);
|
||||||
|
|
||||||
|
// Check indexes
|
||||||
|
const designDoc = await db.get('_design/adopt-a-street');
|
||||||
|
const indexCount = Object.keys(designDoc.indexes || {}).length;
|
||||||
|
console.log(`✅ ${indexCount} indexes created`);
|
||||||
|
|
||||||
|
// Check badges
|
||||||
|
const badges = await db.find({
|
||||||
|
selector: { type: 'badge' },
|
||||||
|
fields: ['name']
|
||||||
|
});
|
||||||
|
console.log(`✅ ${badges.docs.length} badges available`);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Setup verification failed:', error.message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async seedAdminUser() {
|
||||||
|
console.log('👤 Seeding admin user...');
|
||||||
|
|
||||||
|
const ADMIN_EMAIL = process.env.ADMIN_EMAIL;
|
||||||
|
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD;
|
||||||
|
|
||||||
|
if (!ADMIN_EMAIL || !ADMIN_PASSWORD) {
|
||||||
|
console.log('⚠️ ADMIN_EMAIL or ADMIN_PASSWORD not set, skipping admin user creation');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = this.nano.use(COUCHDB_DB_NAME);
|
||||||
|
|
||||||
|
// Check if admin user already exists
|
||||||
|
try {
|
||||||
|
const existing = await db.find({
|
||||||
|
selector: { type: 'user', email: ADMIN_EMAIL },
|
||||||
|
limit: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existing.docs.length > 0) {
|
||||||
|
const user = existing.docs[0];
|
||||||
|
if (!user.isAdmin) {
|
||||||
|
user.isAdmin = true;
|
||||||
|
user.updatedAt = new Date().toISOString();
|
||||||
|
await db.insert(user);
|
||||||
|
console.log('✅ Existing user promoted to admin');
|
||||||
|
} else {
|
||||||
|
console.log('ℹ️ Admin user already exists');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Continue with creation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new admin user with hashed password
|
||||||
|
const bcrypt = require('bcryptjs');
|
||||||
|
const salt = await bcrypt.genSalt(10);
|
||||||
|
const hashedPassword = await bcrypt.hash(ADMIN_PASSWORD, salt);
|
||||||
|
|
||||||
|
const adminUser = {
|
||||||
|
_id: `user_admin_${Date.now()}`,
|
||||||
|
type: 'user',
|
||||||
|
name: 'Administrator',
|
||||||
|
email: ADMIN_EMAIL,
|
||||||
|
password: hashedPassword,
|
||||||
|
isAdmin: true,
|
||||||
|
isPremium: true,
|
||||||
|
points: 0,
|
||||||
|
avatar: null,
|
||||||
|
profilePicture: null,
|
||||||
|
bio: 'System Administrator',
|
||||||
|
location: '',
|
||||||
|
website: '',
|
||||||
|
social: { twitter: '', github: '', linkedin: '' },
|
||||||
|
privacySettings: { profileVisibility: 'private' },
|
||||||
|
preferences: { emailNotifications: true, pushNotifications: true, theme: 'light' },
|
||||||
|
adoptedStreets: [],
|
||||||
|
completedTasks: [],
|
||||||
|
posts: [],
|
||||||
|
events: [],
|
||||||
|
earnedBadges: [],
|
||||||
|
stats: { streetsAdopted: 0, tasksCompleted: 0, postsCreated: 0, eventsParticipated: 0, badgesEarned: 0 },
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
updatedAt: new Date().toISOString()
|
||||||
|
};
|
||||||
|
|
||||||
|
await db.insert(adminUser);
|
||||||
|
console.log(`✅ Admin user created: ${ADMIN_EMAIL}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async run() {
|
||||||
|
try {
|
||||||
|
await this.initialize();
|
||||||
|
await this.createDatabase();
|
||||||
|
await this.createIndexes();
|
||||||
|
await this.createSecurityDocument();
|
||||||
|
await this.seedBadges();
|
||||||
|
await this.seedAdminUser();
|
||||||
|
await this.verifySetup();
|
||||||
|
|
||||||
|
console.log('\n🎉 CouchDB setup completed successfully!');
|
||||||
|
console.log(`\n📋 Connection Details:`);
|
||||||
|
console.log(` URL: ${COUCHDB_URL}`);
|
||||||
|
console.log(` Database: ${COUCHDB_DB_NAME}`);
|
||||||
|
console.log(` User: ${COUCHDB_USER}`);
|
||||||
|
console.log(`\n🌐 Access CouchDB at: ${COUCHDB_URL}/_utils`);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('\n❌ Setup failed:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run setup if called directly
|
||||||
|
if (require.main === module) {
|
||||||
|
const setup = new CouchDBSetup();
|
||||||
|
setup.run().catch(console.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = CouchDBSetup;
|
||||||
@@ -20,8 +20,15 @@ spec:
|
|||||||
- sh
|
- sh
|
||||||
- -c
|
- -c
|
||||||
- |
|
- |
|
||||||
until curl -f -s http://adopt-a-street-couchdb:5984/_up > /dev/null 2>&1; do
|
COUNT=0
|
||||||
echo "Waiting for CouchDB to be ready..."
|
MAX_ATTEMPTS=60
|
||||||
|
until curl -f -s http://adopt-a-street-couchdb.adopt-a-street.svc.cluster.local:5984/_up > /dev/null 2>&1; do
|
||||||
|
COUNT=$((COUNT+1))
|
||||||
|
if [ $COUNT -ge $MAX_ATTEMPTS ]; then
|
||||||
|
echo "Timeout waiting for CouchDB after $MAX_ATTEMPTS attempts"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Waiting for CouchDB to be ready... (attempt $COUNT/$MAX_ATTEMPTS)"
|
||||||
sleep 3
|
sleep 3
|
||||||
done
|
done
|
||||||
echo "CouchDB is ready!"
|
echo "CouchDB is ready!"
|
||||||
|
|||||||
@@ -45,6 +45,21 @@ spec:
|
|||||||
operator: In
|
operator: In
|
||||||
values:
|
values:
|
||||||
- arm64 # Pi 5 architecture
|
- arm64 # Pi 5 architecture
|
||||||
|
initContainers:
|
||||||
|
- name: setup-config
|
||||||
|
image: busybox:1.36
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
echo "[chttpd]" > /opt/couchdb/etc/local.d/bind.ini
|
||||||
|
echo "bind_address = 0.0.0.0" >> /opt/couchdb/etc/local.d/bind.ini
|
||||||
|
cat /opt/couchdb/etc/local.d/bind.ini
|
||||||
|
volumeMounts:
|
||||||
|
- name: couchdb-data
|
||||||
|
mountPath: /opt/couchdb/data
|
||||||
|
- name: local-config
|
||||||
|
mountPath: /opt/couchdb/etc/local.d
|
||||||
containers:
|
containers:
|
||||||
- name: couchdb
|
- name: couchdb
|
||||||
image: couchdb:3.3
|
image: couchdb:3.3
|
||||||
@@ -71,30 +86,39 @@ spec:
|
|||||||
key: COUCHDB_SECRET
|
key: COUCHDB_SECRET
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
memory: "512Mi"
|
memory: "256Mi"
|
||||||
cpu: "250m"
|
cpu: "100m"
|
||||||
limits:
|
limits:
|
||||||
memory: "2Gi"
|
memory: "1Gi"
|
||||||
cpu: "1000m"
|
cpu: "500m"
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: couchdb-data
|
- name: couchdb-data
|
||||||
mountPath: /opt/couchdb/data
|
mountPath: /opt/couchdb/data
|
||||||
|
- name: local-config
|
||||||
|
mountPath: /opt/couchdb/etc/local.d
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
exec:
|
||||||
path: /_up
|
command:
|
||||||
port: 5984
|
- curl
|
||||||
|
- -f
|
||||||
|
- http://localhost:5984/_up
|
||||||
initialDelaySeconds: 60
|
initialDelaySeconds: 60
|
||||||
periodSeconds: 10
|
periodSeconds: 10
|
||||||
timeoutSeconds: 5
|
timeoutSeconds: 5
|
||||||
failureThreshold: 6
|
failureThreshold: 6
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
exec:
|
||||||
path: /_up
|
command:
|
||||||
port: 5984
|
- curl
|
||||||
|
- -f
|
||||||
|
- http://localhost:5984/_up
|
||||||
initialDelaySeconds: 30
|
initialDelaySeconds: 30
|
||||||
periodSeconds: 10
|
periodSeconds: 10
|
||||||
timeoutSeconds: 5
|
timeoutSeconds: 5
|
||||||
failureThreshold: 6
|
failureThreshold: 6
|
||||||
|
volumes:
|
||||||
|
- name: local-config
|
||||||
|
emptyDir: {}
|
||||||
|
|
||||||
volumeClaimTemplates:
|
volumeClaimTemplates:
|
||||||
- metadata:
|
- metadata:
|
||||||
|
|||||||
Reference in New Issue
Block a user