How do I create a Kubernetes Custom Resource using javascript client - javascript

My custom definition
apiVersion: something.com/v1alpha1
kind: MyKind
metadata:
name: test
spec:
size: 1
image: myimage
Here is an answer that shows how to create a deployment using a javascript client. However, I need to create a custom resource using a javascript client

All the client libraries are auto-generated from the same underlying IDL so it works like in Go, createNamespacedCustomObject. You can also use the raw API directly too.

const k8s = require('#kubernetes/client-node')
const kc = new k8s.KubeConfig();
kc.loadFromDefault();
const k8sClient = kc.makeApiClient(k8s.CustomObjectsApi);
var body = {
"apiVersion": "something.com/v1alpha1",
"kind": "MyKind",
"metadata": {
"name": "mycustomobject",
},
"spec": {
"size": "1",
"image": "myimage"
}
}
k8sClient.createNamespacedCustomObject('something.com','v1alpha1','default','mykinds', body)
.then((res)=>{
console.log(res)
})
.catch((err)=>{
console.log(err)
})

Related

Patch custom object with kubernetes javascrtip SDK

I'm using External Secrets to sync my secrets from azure. And now I need a programmatic way to trigger the sync. With kubectl the command is
kubectl annotate es my-es force-sync=$(date +%s) --overwrite
So, I try to use k8s js sdk to do this. I can success fully get the External Secret
await crdApi.getNamespacedCustomObject("external-secrets.io", "v1beta1", "default", "externalsecrets", "my-es")
However, when I try to update it with patchNamespacedCustomObject, it always tells me "the body of the request was in an unknown format - accepted media types include: application/json-patch+json, application/merge-patch+json, application/apply-patch+yaml"
Here's my code
const kc = new k8s.KubeConfig();
kc.loadFromString(kubeConfig);
const crdApi = kc.makeApiClient(k8s.CustomObjectsApi);
let patch = [{
"op": "replace",
"path": "/metadata/annotations",
"value": {
"force-sync": "1663315075"
}
}];
await crdApi.patchNamespacedCustomObject("external-secrets.io", "v1beta1", "default", "externalsecrets", "my-es", patch);
I am referring their patch example here
const options = {
"headers": {
"Content-type": k8s.PatchUtils.PATCH_FORMAT_JSON_PATCH
}
};
is still required.

Getting Status code 422 when creating Kubernetes Job using nodejs

I am creating a Kubernetes Job within NodeJS class After importing the library #kubernetes/client-node, I created an object to use the module BatchV1Api inside the function which I am exporting to other class in which I have defined the body of the Kubernetes job like this:
//listJobs.js
import { post } from '../kubeClient.js';
const kubeRoute = async (ctx) => {
const newJob = {
metadata: {
name: 'countdown',
},
spec: {
template: {
metadata: {
name: 'countdown',
},
},
spec: {
containers: [
{
name: 'counter',
image: 'centos:7',
command: 'bin/bash, -c, for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done',
}],
restartPolicy: 'Never',
},
},
};
const kubeClient = post();
kubeClient.createNamespacedJob('default', newJob);
ctx.body = {
// listConfigMap: (await kubeClient.listConfigMapForAllNamespaces()).body,
listJobs: (await kubeClient.listJobForAllNamespaces()).body,
// listService: (await kubeClient.listServiceForAllNamespaces()).body,
};
};
export default kubeRoute;
Then I created a router class to request the post method like:
import post from './listJobs.js';
const apiRouter = new Router();
apiRouter.post('/api/v1/newJob', post);
when executing the application and requesting the route localhost:3000/api/v1/newJob as a post request in postman, it is showing status code 422 (with some very long output, as in the screenshot) in the vs code terminal and some Kubernetes information in postman body, but it is not creating any job or pod.
Does anyone have any idea, why there is 422 code at the end?
Status code 422 Unprocessable Entity means that server understand the content type, and the syntax of the request is correct, but it was unable to process the contained instructions.
In your case though, the Job manifest looks off.
I'm not an expert in JavaScript kubernetes client, but newJob body looks weird. The resulting yaml should look like this
apiVersion: batch/v1
kind: Job
metadata:
name: countdown
spec:
template:
spec:
containers:
- name: counter
image: centos:7
command: 'bin/bash, -c, for i in {9..1} ; do echo $i ; done' #fixed this one for you
restartPolicy: Never
In your case the second spec is a child of spec. It should be a child of template, so:
{
"metadata": {
"name": "countdown"
},
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "counter",
"image": "centos:7",
"command": "bin/bash, -c, for i in {9..1} ; do echo $i ; done"
}
],
"restartPolicy": "Never"
}
}
}
}

How to create tree via Github API?

I am trying programmatically create a git commit and as part of that I need to create a git tree.
Having read the docs, I am unsure what to send in the request body.
I am able to create a blob and get a sha response but when I try call the create tree endpoint, I get the following:
{
"url": "https://api.github.com/repos/<owner>/<repo>/git/trees/",
"status": 404,
"statusText": "Not Found",
"body": {
"message": "Not Found",
"documentation_url": "https://docs.github.com/rest"
}
}
My code looks like this where I create the blob and then try create the tree:
const blobContent = fs.readFileSync(__dirname + '/../../../templates/main.yaml', { encoding: "utf8" })
const blob = await this.post<IBlobResponse>(`https://api.github.com/repos/${ownerName}/${repoName}/git/blobs`, {
content: blobContent,
encoding: "utf-8"
})
const tree = await this.post(`https://api.github.com/repos/${ownerName}/${repoName}/git/trees/`, {
base_tree: masterRef.object.sha,
tree: [
{
path: "main.yaml",
mode: "100644",
type: "tree",
sha: blob.sha,
content: blobContent
}
]
})
Is the payload for creating the tree correct?
Should path be the local relative path or is it the path that the file will live in inside the repository?
Do I need both the sha and the content?
Is the fact that the content is a yaml file an issue?
Turns out I was including a trailing / in the POST endpoint when creating a tree:
Changed https://api.github.com/repos/${ownerName}/${repoName}/git/trees/ to https://api.github.com/repos/${ownerName}/${repoName}/git/trees and it worked.
Very simple fix but thought I'd share incase anybody else has a similar issue

Not able to autheticate google cloud vision api . How to autheticate it to use it further

My Code looks like this :-
var vision = require('#google-cloud/vision');
handleSubmit = () =>{
console.log("encoded string submitted=",this.state.files);
this.useVisionCloud();
}
useVisionCloud = () =>{
const client = new vision.ImageAnnotatorClient();
const request_body = {
"requests": [
{
"image": {
"content": this.state.files
},
"features": [
{
"type": "TEXT_DETECTION"
}
]
}
]
};
client.textDetection(request_body).then(response => {
console.log("text got=",response);
// doThingsWith(response);
})
.catch(err => {
console.log("error got=",err);
});
}
I already tried setting environment variable but didn't work .
I have also created service account and downloaded the file.json
but dont know how to use it for authentication
im getting the following error :-
Uncaught Error: {"clientConfig":{},"port":443,"servicePath":"vision.googleapis.com","scopes":["https://www.googleapis.com/auth/cloud-platform","https://www.googleapis.com/auth/cloud-vision"]}You need to pass auth instance to use gRPC-fallback client in browser. Use OAuth2Client from google-auth-library.
on triggering a post request to Google API .
Final Query is :- I am not able to understand how to authenticate API so that i can further use it to detect text in my images
Set the env variable eg:
export GOOGLE_APPLICATION_CREDENTIALS="[PATH]"
I would recommend having a separate backend that calls vision api. Then have the javascript code in your browser call your backend.

Error serving HTML files from an Azure function

I am trying to open, read and return an HTML files using Azure functions. I am developing locally and the logs says that the function executed successfully however on the browser I am getting 500 internal server error. Am I doing something wrong in here?
const fs = require('fs');
const path = require('path');
const mime = require('../node_modules/mime-types');
module.exports = function (context, req) {
const staticFilesFolder = 'www/build/';
const defaultPage = 'index.html';
getFile(context, req.query.file);
function getFile(context, file) {
const homeLocation = process.env["HOME"];
if(!file || file == null || file === undefined){
context.done(null,{status:200,body:"<h1>Define a file</h1>",headers:{
"Content-Type":" text/html; charset=utf-8"
}});
}
fs.readFile(path.resolve(path.join(homeLocation, staticFilesFolder, file)),
(err, htmlContent) => {
if (err) {
getFile(context, "404.html");
}
else {
const res = {
status: 200,
body: htmlContent,
headers:{
"Content-Type": mime.lookup(path.join(homeLocation, staticFilesFolder, file))
}
}
context.done(null,res);
}
})
}
};
Note
I am sure that 404.html exists and index.html exists. When I log the contents of htmlContent it is giving the correct output.
functions.json
{
"disabled": false,
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"methods":["get"],
"route":"home",
"name": "req"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
Response on Chrome
If I removed "Content-Length" header the status code changes to 406.
Update 1 The code seems to be running normally on Azure Portal but it is not working when running it locally.
It looks like you are combining two methods of returning data from an http triggered function(context.res and context.done()): https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-node#accessing-the-request-and-response
Since you are using context.res, try removing context.done();
You are making an incorrect use of context.res, you shouldn't be overwriting it but instead leveraging the methods provided by the Response class provided in the Azure NodeJS worker. If you are using using VSCode you'll get intellisense for these methods. Otherwise see: https://github.com/Azure/azure-functions-nodejs-worker/blob/dev/src/http/Response.ts
Your code should look something like this instead.
context.res.setHeader('content-type', 'text/html; charset=utf-8')
context.res.raw(htmlContent)
Using context.res.raw or context.res.send will already perform the context.done call for you.
Make sure you use content-type=text/html; charset-utf8 instead of content-type=text/html or you'll trigger an issue with the returned content-type. Instead of returning content-type=text/html you end up getting content-type=text/plain which will fail to render your html.
Addressed on: https://github.com/Azure/azure-webjobs-sdk-script/issues/2053

Categories