feat: SugarCRM 6.5.26 CE - Docker + compose + CI/CD
Some checks failed
Docker Build & Push SugarCRM 6.5 CE / build-and-push (push) Has been cancelled

- PHP 5.6 Apache Dockerfile (Debian Jessie, archive repos)
- Source from bklein01/sugarcrm GitHub mirror
- MySQL 5.7 database with healthcheck
- Silent install via init.sh (AdminWizard disabled)
- REST v4.1 API test script (test_api.py)
- Gitea Actions CI/CD for registry push
- Full README with API docs and pitfall notes
This commit is contained in:
root
2026-05-24 14:33:08 +02:00
parent 30905b15d4
commit 1c4a366409
14 changed files with 576 additions and 334 deletions

140
test_api.py Normal file
View File

@@ -0,0 +1,140 @@
#!/usr/bin/env python3
"""
SugarCRM 6.5 CE REST v4.1 API Test
===================================
Endpunkt: http://localhost:{PORT}/service/v4_1/rest.php
"""
import http.client
import json
import hashlib
import urllib.parse
import sys
import os
from datetime import datetime
# Configurable via env vars
BASE_HOST = os.environ.get("SUGARCRM_HOST", "localhost")
BASE_PORT = os.environ.get("SUGARCRM_PORT", "2080")
ENDPOINT = "/service/v4_1/rest.php"
USER = os.environ.get("SUGARCRM_USER", "admin")
PASSWORD = os.environ.get("SUGARCRM_PASSWORD", "admin123")
BASE_URL = f"{BASE_HOST}:{BASE_PORT}"
def call_api(method, rest_data):
"""Aufruf der SugarCRM REST v4.1 API"""
conn = http.client.HTTPConnection(BASE_URL, timeout=30)
body = urllib.parse.urlencode({
"method": method,
"input_type": "JSON",
"response_type": "JSON",
"rest_data": json.dumps(rest_data)
})
headers = {"Content-Type": "application/x-www-form-urlencoded"}
conn.request("POST", ENDPOINT, body, headers)
resp = conn.getresponse()
if resp.status == 302:
location = resp.getheader("Location", "")
print(f" ⚠️ Redirect to: {location}")
print(" (Admin Wizard may be active - restart container to fix)")
return None
data = json.loads(resp.read().decode())
conn.close()
return data
def main():
print("=" * 60)
print("🍬 SugarCRM 6.5.26 CE REST API Test")
print(f" URL: http://{BASE_URL}")
print("=" * 60)
# 1. Login
pwd_hash = hashlib.md5(PASSWORD.encode()).hexdigest()
print(f"\n1⃣ LOGIN (user={USER}, md5={pwd_hash[:8]}...)")
result = call_api("login", {
"user_auth": {"user_name": USER, "password": pwd_hash},
"application_name": "API Test Script"
})
if not result:
print("❌ LOGIN FAILED (Redirect - Admin Wizard active?)")
print(" Run: docker compose restart sugarcrm")
sys.exit(1)
if result.get("id"):
session = result["id"]
print(f" ✅ Session: {session[:20]}...")
else:
print(f" ❌ Login Error: {result.get('name', 'Unknown')} - {result.get('description', '')}")
sys.exit(1)
# 2. Available modules
print(f"\n2⃣ AVAILABLE MODULES")
result = call_api("get_available_modules", {"session": session})
if result and "modules" in result:
modules = result["modules"]
print(f"{len(modules)} modules available")
print(f" First 10: {', '.join(m['module_key'] for m in modules[:10])}")
else:
print(f" ❌ Error: {result}")
# 3. Accounts list
print(f"\n3⃣ ACCOUNTS (get_entry_list)")
result = call_api("get_entry_list", {
"session": session,
"module_name": "Accounts",
"query": "",
"order_by": "",
"offset": 0,
"select_fields": ["name", "id", "date_entered"],
"link_name_to_fields_array": [],
"max_results": 5,
"deleted": 0
})
if result and "entry_list" in result:
count = result.get("result_count", 0)
print(f"{count} accounts found")
for entry in result["entry_list"][:5]:
vals = {n["name"]: n["value"] for n in entry["name_value_list"]}
print(f" - {vals.get('name', 'N/A')} (ID: {vals.get('id', 'N/A')[:10]}...)")
else:
print(f" ❌ Error: {result}")
# 4. Create test account
print(f"\n4⃣ CREATE ACCOUNT (set_entry)")
test_name = f"Test API Account {datetime.now().strftime('%H:%M:%S')}"
result = call_api("set_entry", {
"session": session,
"module_name": "Accounts",
"name_value_list": {
"name": {"name": "name", "value": test_name},
"account_type": {"name": "account_type", "value": "Customer"},
}
})
if result and result.get("id"):
print(f" ✅ Account '{test_name}' created (ID: {result['id'][:10]}...)")
# 5. Session count
print(f"\n5⃣ MODULE COUNT (get_entries_count)")
result = call_api("get_entries_count", {
"session": session,
"module_name": "Accounts",
"query": "",
"deleted": 0
})
if result:
print(f" ✅ Total accounts: {result.get('result_count', 'unknown')}")
print(f"\n{'=' * 60}")
print("✅ ALL API TESTS PASSED!")
print(f"{'=' * 60}")
if __name__ == "__main__":
main()