help wanted
Description
I wanted to kick off a job in my GKE cluster from a Google Cloud Function reacting to changes in Cloud Storage. Since there's no .kube/config it wasn't clear to me how to do that with the new fromKubeConfig initialization. I got it working by piecing together a config object from data retrieved by google-auth-library and @google-cloud/container clients. I'll leave it here to both ask if this way makes sense and to serve as an example for others trying to do something similar.
const {auth} = require('google-auth-library');
const container = require('@google-cloud/container');
const job = require('./job.json');
const kube = require('kubernetes-client');
const clusterClient = new container.v1.ClusterManagerClient();
const request = {
projectId: process.env.GCLOUD_PROJECT,
zone: 'us-east4-b',
clusterId: 'cluster-2',
};
function getCluster() {
return clusterClient.getCluster(request)
.then(results => {
return results[0];
});
}
function getToken() {
return auth.getClient()
.then(client => {
return client.getAccessToken();
})
.then(tokenResponse => {
return tokenResponse.token;
});
}
// kubeClient is a lazy global used for caching.
// https://cloud.google.com/functions/docs/bestpractices/tips#use_global_variables_to_reuse_objects_in_future_invocations
let kubeClient;
function getKubeClient(cluster, token) {
kubeClient = new kube.Client({config: kube.config.fromKubeconfig({
apiVersion: 'v1',
kind: 'Config',
preferences: {},
'current-context': 'a',
contexts: [
{
name: 'a',
context: {
cluster: 'a',
user: 'a'
}
}
],
clusters: [
{
name: 'a',
cluster: {
'certificate-authority-data': cluster.masterAuth.clusterCaCertificate,
server: `https://${cluster.endpoint}`
}
}
],
users: [
{
name: 'a',
user: {
'auth-provider': {
config: {
'access-token': token,
'cmd-args': 'config config-helper --format=json',
'cmd-path': '/google/google-cloud-sdk/bin/gcloud',
'token-key': '{.credential.access_token}'
},
name: 'gcp'
}
}
}
]
})});
return kubeClient.loadSpec();
}
exports.updateJob = (event) => {
return (kubeClient && Promise.resolve(kubeClient) ||
Promise.all([getCluster(), getToken()]).then(([cluster, token]) => {
return getKubeClient(cluster, token);
}))
.then(kubeClient => {
// Strip extension from filename to get job name
const name = event.data.name.replace(/\.[^/.]+$/, "");
job.metadata.generateName = `${name}-update-`;
job.spec.template.spec.volumes[0].configMap.name = name;
return kubeClient.apis.batch.v1.namespaces('default').jobs.post({body: job});
})
.then(res => {
console.log('Job created:', res.body.metadata.name);
});
};