Skip to content

Commit

Permalink
linter updates
Browse files Browse the repository at this point in the history
  • Loading branch information
mfreeman451 committed Feb 26, 2025
1 parent 826b11c commit 1edeb17
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 23 deletions.
116 changes: 116 additions & 0 deletions pkg/cloud/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ package api
import (
"embed"
"encoding/json"
"fmt"
"io"
"io/fs"
"log"
"net/http"
"os"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -109,12 +113,122 @@ func (s *APIServer) setupStaticFileServing() {
fsys, err := fs.Sub(webContent, "web/dist")
if err != nil {
log.Printf("Error setting up static file serving: %v", err)

return
}

s.router.PathPrefix("/").Handler(http.FileServer(http.FS(fsys)))
}

func (s *APIServer) setupWebProxyRoutes(listenAddr string) {
// Create a separate router for web-to-API proxy
webProxyRouter := mux.NewRouter()

// Add common middleware but skip API key validation
webProxyRouter.Use(srHttp.CommonMiddleware)

// Create a closure to capture the listen address
proxyHandler := func(w http.ResponseWriter, r *http.Request) {
s.proxyAPIRequest(w, r, listenAddr)
}

// Create handlers for proxying API requests
webProxyRouter.PathPrefix("/web-api/").HandlerFunc(proxyHandler)

// Add the web proxy router to the main router
s.router.PathPrefix("/web-api/").Handler(webProxyRouter)
}

// proxyAPIRequest forwards an incoming request to an internal API server.
func (s *APIServer) proxyAPIRequest(w http.ResponseWriter, r *http.Request, serverAddr string) {
// Build the internal API URL
apiPath := strings.TrimPrefix(r.URL.Path, "/web-api/")
internalURL := fmt.Sprintf("http://%s/api/%s", serverAddr, apiPath)

if r.URL.RawQuery != "" {
internalURL += "?" + r.URL.RawQuery
}

// Create a new request with context
proxyReq, err := http.NewRequestWithContext(r.Context(), r.Method, internalURL, r.Body)
if err != nil {
s.writeError(w, "Failed to create proxy request", http.StatusInternalServerError)

return
}

// Set headers on the proxy request
s.setProxyHeaders(proxyReq, r)

// Execute the proxied request
resp, err := s.executeRequest(proxyReq)
if err != nil {
s.writeError(w, "Failed to execute request", http.StatusInternalServerError)

return
}

// Ensure the body is closed after we're done
defer func() {
if err = resp.Body.Close(); err != nil {
log.Printf("Failed to close response body: %v", err)
}
}()

// Copy response to the client
if err = s.copyResponse(w, resp); err != nil {
s.writeError(w, "Failed to copy response body", http.StatusInternalServerError)

return
}
}

// setProxyHeaders adds headers to the proxied request, including API key.
func (*APIServer) setProxyHeaders(proxyReq, originalReq *http.Request) {
if apiKey := os.Getenv("API_KEY"); apiKey != "" {
proxyReq.Header.Set("X-API-Key", apiKey)
}

for name, values := range originalReq.Header {
if !strings.EqualFold(name, "x-api-key") {
for _, value := range values {
proxyReq.Header.Add(name, value)
}
}
}
}

// executeRequest performs the HTTP request.
func (*APIServer) executeRequest(req *http.Request) (*http.Response, error) {
client := &http.Client{}

return client.Do(req)
}

// copyResponse writes the response headers and body to the writer.
func (*APIServer) copyResponse(w http.ResponseWriter, resp *http.Response) error {
for name, values := range resp.Header {
for _, value := range values {
w.Header().Add(name, value)
}
}

w.WriteHeader(resp.StatusCode)

_, err := io.Copy(w, resp.Body)
if err != nil {
log.Printf("Failed to copy response body: %v", err)
}

return err
}

// writeError writes an HTTP error response and logs the issue.
func (*APIServer) writeError(w http.ResponseWriter, msg string, status int) {
http.Error(w, msg, status)
log.Printf("%s: %d", msg, status)
}

func (s *APIServer) setupRoutes() {
// Create a middleware chain
middlewareChain := func(next http.Handler) http.Handler {
Expand Down Expand Up @@ -425,6 +539,8 @@ const (
)

func (s *APIServer) Start(addr string) error {
s.setupWebProxyRoutes(addr)

srv := &http.Server{
Addr: addr,
Handler: s.router,
Expand Down
44 changes: 21 additions & 23 deletions scripts/setup-deb-cloud.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,61 +17,53 @@ mkdir -p "${PKG_ROOT}/usr/local/share/serviceradar-cloud/web"

echo "Building web interface..."

# Build web interface if not already built
if [ ! -d "web/dist" ]; then
cd ./web
npm install
npm run build
cd ..
fi

# Create a directory for the embedded content
mkdir -p pkg/cloud/api/web
cp -r web/dist pkg/cloud/api/web/

# Only copy web assets to package directory for container builds
# For non-container builds, they're embedded in the binary
if [[ "$BUILD_TAGS" == *"containers"* ]]; then
cp -r web/dist "${PKG_ROOT}/usr/local/share/serviceradar-cloud/web/"
echo "Copied web assets for container build"
fi

echo "Building Go binary..."

# Build Go binary with or without container tags
BUILD_CMD="CGO_ENABLED=1 GOOS=linux GOARCH=amd64"
if [[ ! -z "$BUILD_TAGS" ]]; then
BUILD_CMD="$BUILD_CMD GOFLAGS=\"-tags=$BUILD_TAGS\""
fi
BUILD_CMD="$BUILD_CMD go build -o \"../../${PKG_ROOT}/usr/local/bin/serviceradar-cloud\""

# Build Go binary
cd cmd/cloud
eval $BUILD_CMD
cd ../..

echo "Creating package files..."

# Create control file
cat > "${PKG_ROOT}/DEBIAN/control" << EOF
Package: serviceradar-cloud
Version: ${VERSION}
Section: utils
Priority: optional
Architecture: amd64
Depends: systemd
Depends: systemd, openssl
Maintainer: Michael Freeman <[email protected]>
Description: ServiceRadar cloud service with web interface
Provides centralized monitoring and web dashboard for ServiceRadar.
Config: /etc/serviceradar/cloud.json
EOF

# Create conffiles to mark configuration files
cat > "${PKG_ROOT}/DEBIAN/conffiles" << EOF
/etc/serviceradar/cloud.json
EOF

# Create systemd service file
# Updated systemd service file with Environment directive
cat > "${PKG_ROOT}/lib/systemd/system/serviceradar-cloud.service" << EOF
[Unit]
Description=ServiceRadar Cloud Service
Expand All @@ -80,6 +72,7 @@ After=network.target
[Service]
Type=simple
User=serviceradar
EnvironmentFile=/etc/serviceradar/cloud.env
ExecStart=/usr/local/bin/serviceradar-cloud -config /etc/serviceradar/cloud.json
Restart=always
RestartSec=10
Expand All @@ -91,9 +84,8 @@ KillSignal=SIGTERM
WantedBy=multi-user.target
EOF

# Create default config only if we're creating a fresh package
# Config file without API key
if [ ! -f "/etc/serviceradar/cloud.json" ]; then
# Create default config file
cat > "${PKG_ROOT}/etc/serviceradar/cloud.json" << EOF
{
"listen_addr": ":8090",
Expand Down Expand Up @@ -133,7 +125,7 @@ if [ ! -f "/etc/serviceradar/cloud.json" ]; then
EOF
fi

# Create postinst script
# Updated postinst script to generate API key in environment file
cat > "${PKG_ROOT}/DEBIAN/postinst" << EOF
#!/bin/bash
set -e
Expand All @@ -143,16 +135,30 @@ if ! id -u serviceradar >/dev/null 2>&1; then
useradd --system --no-create-home --shell /usr/sbin/nologin serviceradar
fi
# Set permissions
# Generate API key and store in environment file if it doesn't exist
ENV_FILE="/etc/serviceradar/cloud.env"
echo "Environment file path: $ENV_FILE"
if [ ! -f "$ENV_FILE" ]; then
echo "Creating environment file..."
mkdir -p /etc/serviceradar
API_KEY=$(openssl rand -hex 16)
echo "Generated API_KEY: $API_KEY"
echo "API_KEY=$API_KEY" > "$ENV_FILE"
echo "Environment file created"
chmod 600 "$ENV_FILE"
chown serviceradar:serviceradar "$ENV_FILE"
fi
# Set permissions for config
chown -R serviceradar:serviceradar /etc/serviceradar
chmod 644 /etc/serviceradar/cloud.json
chmod 755 /usr/local/bin/serviceradar-cloud
# Create data directory
mkdir -p /var/lib/serviceradar
chown -R serviceradar:serviceradar /var/lib/serviceradar
chmod 755 /var/lib/serviceradar
# Set permissions for web assets
if [ -d "/usr/local/share/serviceradar-cloud/web" ]; then
chown -R serviceradar:serviceradar /usr/local/share/serviceradar-cloud
chmod -R 755 /usr/local/share/serviceradar-cloud
Expand All @@ -168,12 +174,10 @@ EOF

chmod 755 "${PKG_ROOT}/DEBIAN/postinst"

# Create prerm script
cat > "${PKG_ROOT}/DEBIAN/prerm" << EOF
#!/bin/bash
set -e
# Stop and disable service
systemctl stop serviceradar-cloud || true
systemctl disable serviceradar-cloud || true
Expand All @@ -184,17 +188,11 @@ chmod 755 "${PKG_ROOT}/DEBIAN/prerm"

echo "Building Debian package..."

# Create release-artifacts directory if it doesn't exist
mkdir -p ./release-artifacts

# Build the package
dpkg-deb --build "${PKG_ROOT}"

# Move the deb file to the release-artifacts directory
mv "${PKG_ROOT}.deb" "./release-artifacts/"

if [[ ! -z "$BUILD_TAGS" ]]; then
# For tagged builds, add the tag to the filename
PACKAGE_NAME="serviceradar-cloud_${VERSION}-${BUILD_TAGS//,/_}.deb"
mv "./release-artifacts/${PKG_ROOT}.deb" "./release-artifacts/$PACKAGE_NAME"
echo "Package built: release-artifacts/$PACKAGE_NAME"
Expand Down

0 comments on commit 1edeb17

Please sign in to comment.