-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
### What changes were proposed in this pull request? Introduces a new `GCPUtils` class that provides a unified interface for interacting with various Google Cloud Platform services: - Secret Manager operations for managing secrets - Cloud Storage methods for file upload/download - Cloud Scheduler functionality for job creation - Cloud Run service deployment capabilities - Cloud SQL database management - Helper methods for resource verification ### Why are the changes needed? To centralize and standardize GCP service interactions within the application, reducing code duplication and providing a consistent interface for common cloud operations. This utility class will make it easier to manage cloud resources and perform common GCP operations throughout the application. ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? Each GCP service method includes error handling and follows GCP best practices. Integration tests should be added to verify interactions with each cloud service in isolation.
- Loading branch information
1 parent
151f0a1
commit dd74e3a
Showing
3 changed files
with
1,672 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import { SecretManagerServiceClient } from "@google-cloud/secret-manager"; | ||
import { CloudSchedulerClient } from "@google-cloud/scheduler"; | ||
import { Storage } from "@google-cloud/storage"; | ||
import { CloudRunClient } from "@google-cloud/run"; | ||
import { Compute } from "@google-cloud/compute"; | ||
|
||
export class GCPUtils { | ||
private secretManager: SecretManagerServiceClient; | ||
private scheduler: CloudSchedulerClient; | ||
private storage: Storage; | ||
private cloudRun: CloudRunClient; | ||
private compute: Compute; | ||
private projectId: string; | ||
|
||
constructor(projectId: string) { | ||
this.projectId = projectId; | ||
this.secretManager = new SecretManagerServiceClient(); | ||
this.scheduler = new CloudSchedulerClient(); | ||
this.storage = new Storage(); | ||
this.cloudRun = new CloudRunClient(); | ||
this.compute = new Compute(); | ||
} | ||
|
||
// Secret Manager Methods | ||
async getSecret(secretName: string, version = "latest"): Promise<string> { | ||
try { | ||
const name = `projects/${this.projectId}/secrets/${secretName}/versions/${version}`; | ||
const [response] = await this.secretManager.accessSecretVersion({ name }); | ||
return response.payload?.data?.toString() || ""; | ||
} catch (error) { | ||
throw new Error(`Failed to get secret: ${error}`); | ||
} | ||
} | ||
|
||
async createSecret(secretId: string, payload: string): Promise<void> { | ||
try { | ||
const parent = `projects/${this.projectId}`; | ||
await this.secretManager.createSecret({ | ||
parent, | ||
secretId, | ||
secret: { | ||
replication: { | ||
automatic: {}, | ||
}, | ||
}, | ||
}); | ||
await this.secretManager.addSecretVersion({ | ||
parent: `projects/${this.projectId}/secrets/${secretId}`, | ||
payload: { | ||
data: Buffer.from(payload, "utf8"), | ||
}, | ||
}); | ||
} catch (error) { | ||
throw new Error(`Failed to create secret: ${error}`); | ||
} | ||
} | ||
|
||
// Cloud Storage Methods | ||
async uploadFile( | ||
bucketName: string, | ||
filePath: string, | ||
destination: string, | ||
): Promise<void> { | ||
try { | ||
const bucket = this.storage.bucket(bucketName); | ||
await bucket.upload(filePath, { | ||
destination, | ||
}); | ||
} catch (error) { | ||
throw new Error(`Failed to upload file: ${error}`); | ||
} | ||
} | ||
|
||
async downloadFile( | ||
bucketName: string, | ||
fileName: string, | ||
destination: string, | ||
): Promise<void> { | ||
try { | ||
const bucket = this.storage.bucket(bucketName); | ||
await bucket.file(fileName).download({ | ||
destination, | ||
}); | ||
} catch (error) { | ||
throw new Error(`Failed to download file: ${error}`); | ||
} | ||
} | ||
|
||
// Cloud Scheduler Methods | ||
async createJob( | ||
jobName: string, | ||
schedule: string, | ||
targetUrl: string, | ||
): Promise<void> { | ||
try { | ||
const parent = `projects/${this.projectId}/locations/us-central1`; | ||
await this.scheduler.createJob({ | ||
parent, | ||
job: { | ||
name: `${parent}/jobs/${jobName}`, | ||
httpTarget: { | ||
uri: targetUrl, | ||
httpMethod: "POST", | ||
}, | ||
schedule, | ||
timeZone: "UTC", | ||
}, | ||
}); | ||
} catch (error) { | ||
throw new Error(`Failed to create job: ${error}`); | ||
} | ||
} | ||
|
||
// Cloud Run Methods | ||
async deployService( | ||
serviceName: string, | ||
image: string, | ||
envVars: Record<string, string> = {}, | ||
): Promise<void> { | ||
try { | ||
const parent = `projects/${this.projectId}/locations/us-central1`; | ||
await this.cloudRun.createService({ | ||
parent, | ||
service: { | ||
name: `${parent}/services/${serviceName}`, | ||
template: { | ||
containers: [ | ||
{ | ||
image, | ||
env: Object.entries(envVars).map(([key, value]) => ({ | ||
name: key, | ||
value, | ||
})), | ||
}, | ||
], | ||
}, | ||
}, | ||
}); | ||
} catch (error) { | ||
throw new Error(`Failed to deploy service: ${error}`); | ||
} | ||
} | ||
|
||
// Helper Methods | ||
async checkResourceExists(resourcePath: string): Promise<boolean> { | ||
try { | ||
await this.secretManager.getProjectParent({ | ||
name: resourcePath, | ||
}); | ||
return true; | ||
} catch { | ||
return false; | ||
} | ||
} | ||
} | ||
|
||
// Export a singleton instance | ||
export const gcpUtils = new GCPUtils(process.env.GOOGLE_CLOUD_PROJECT || ""); |
Oops, something went wrong.