How to run bash script in an already created/exisitng VM in GCP using NodeJS? - node.js

I have gone through, Nodejs-GCP-Compute-Github doc and used the sample code to create a new VM and list existing VM using NodeJS and Npm module.
Now I want to connect to my existing VM and run a small bash script to invoke a few commands mostly git clone or curl to run files in VM.
I couldn't find a method in #google-cloud/compute to connect to the exisitng VMs and do some stuff.
Do we have any such method?
Is it possible to do this in some other way using Nodejs?

There are two different methods coming to my mind:
You could add your public key to the instance, and then connect to it via ssh using a node ssh library (https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keys)
Set a startup script for the instance when you are creating it. This can be done by setting the second parameter (config) of createVM to something like:
{
os: 'ubunntu',
metadata: {
'startup-script': 'your commands'
}
}

Related

How to delete GKE (Google Kubernetes Engine) cluster using python?

I'm new to GKE-Python. I would like to delete my GKE(Google Kubernetes Engine) cluster using a python script.
I found an API delete_cluster() from the google-cloud-container python library to delete the GKE cluster.
https://googleapis.dev/python/container/latest/index.html
But I'm not sure how to use that API by passing the required parameters in python. Can anyone explain me with an example?
Or else If there is any other way to delete the GKE cluster in python?
Thanks in advance.
First you'd need to configure the Python Client for Google Kubernetes Engine as explained on this section of the link you shared. Basically, set up a virtual environment and install the library with pip install google-cloud-container.
If you are running the script within an environment such as the Cloud Shell with an user that has enough access to manage the GKE resources (with at least the Kubernetes Engine Cluster Admin permission assigned) the client library will handle the necessary authentication from the script automatically and the following script will most likely work:
from google.cloud import container_v1
project_id = "YOUR-PROJECT-NAME" #Change me.
zone = "ZONE-OF-THE-CLUSTER" #Change me.
cluster_id = "NAME-OF-THE-CLUSTER" #Change me.
name = "projects/"+project_id+"/locations/"+zone+"/clusters/"+cluster_id
client = container_v1.ClusterManagerClient()
response = client.delete_cluster(name=name)
print(response)
Notice that as per the delete_cluster method documentation you only need to pass the name parameter. If by some reason you are just provided the credentials (generally in the form of a JSON file) of a service account that has enough permissions to delete the cluster you'd need to modify the client for the script and use the credentials parameter to get the client correctly authenticated in a similar fashion to:
...
client = container_v1.ClusterManagerClient(credentials=credentials)
...
Where the credentials variable is pointing to the JSON filename (and path if it's not located in the folder where the script is running) of the service account credentials file with enough permissions that was provided.
Finally notice that the response variable that is returned by the delete_cluster method is of the Operations class which can serve to monitor a long running operation in a similar fashion as to how it is explained here with the self_link attribute corresponding to the long running operation.
After running the script you could use a curl command in a similar fashion to:
curl -X GET \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
https://container.googleapis.com/v1/projects/[RPOJECT-NUMBER]/zones/[ZONE-WHERE-THE-CLUSTER-WAS-LOCATED]/operations/operation-[OPERATION-NUMBER]
by checking the status field (which could be in RUNNING state while it is happening) of the response to that curl command. Or your could also use the requests library or any equivalent to automate this checking procedure of the long running operation within your script.
This page contains an example for the command you are trying to perform.
To give some more details that are required for the command to succeed -
Your environment needs to contain environment variables, this page contains instructions for how to do that.
Once your environment is successfully authenticated we can run the delete cluster command like so -
from google.cloud import container_v1
client = container_v1.ClusterManagerClient()
response = client.delete_cluster(name=projects/<project>/locations/<location>/clusters/<cluster>)

Using gcloud commands in nodejs application

Some gcloud commands don't have API or client library support (for example - this one).
In these cases, is there a simple way to run gcloud commands from a nodejs application?
The gcloud endpoints service commands for IAM policy are difficult for me to check quickly but, if IIRC (and if this is similar to gcloud projects commands for IAM policy), it's not that there's no API, but that there's no single API call.
What you can always do with gcloud is append --log-http to see what happens beneath the covers. With IAM policy mutations (off-top-of-head), you get the policy, mutate it, and then apply the changes back using the etag the GET gave you. The backend checks the policy's state (the etag is like a hash of the policy) and, if it's unchanged, you can make the change.
If this is what's happening here, you should be able to repro the functionality in NodeJS using the existing (!) APIs and, if you're using API Client Libraries (rather than Cloud Client libraries), the functionality will be available.
Apart from the complexity involved in shelling out to gcloud, you'll need to also authenticate it and then you'll need to (un)marshal data to the shell and manage errors. Ergo, it's messy and generally discouraged.
In node.js ,we have child_process module. As the name suggests the child_process provides function like spawn or exec that creates new child process that executes shell command like independent process. spawn is a function that takes the main command as
first argument and other command line options as an array values in place of second parameter.
So with respect to link that you share, you might end-up writing something like this :
const { spawn } = require("child_process");
const listening = spawn('gcloud', ['endpoints', 'services', 'blah', '--option','someValue']);
listening.stdout.on("data", data => {
console.log(`stdout: ${data}`);
});
listening.stderr.on("data", data => {
console.log(`stderr: ${data}`);
});
listening.on('error', (error) => {
console.log(`error: ${error.message}`);
});
References :
https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
I'm not sure this directly answers your question but there is an npm package that can help you run unix commands from within the app.
Check out shell.js

Docker environment variables, dokku-redis

Using redis as my session store in my express.js app. I'm having problems. Narrowed them down to a connection issue.
How do I access a docker environment variable from within an express.js app? I'm using dokku-redis.
It reports that environment variables are automatically set up on the linked app... I've linked my app. running dokku redis:info foo shows that all is linked. I'm trying to pull in REDIS_URL
Thanks, Rob
https://github.com/dokku/dokku-redis
------------
a redis service can be linked to a
container this will use native docker
links via the docker-options plugin
here we link it to our 'playground' app
NOTE: this will restart your app
dokku redis:link lolipop playground
the following environment variables will be set automatically by docker (not on the app itself, so they won’t be listed when calling dokku config)
DOKKU_REDIS_LOLIPOP_NAME=/lolipop/DATABASE
DOKKU_REDIS_LOLIPOP_PORT=tcp://172.17.0.1:6379
DOKKU_REDIS_LOLIPOP_PORT_6379_TCP=tcp://172.17.0.1:6379
DOKKU_REDIS_LOLIPOP_PORT_6379_TCP_PROTO=tcp
DOKKU_REDIS_LOLIPOP_PORT_6379_TCP_PORT=6379
DOKKU_REDIS_LOLIPOP_PORT_6379_TCP_ADDR=172.17.0.1
and the following will be set on the linked application by default
REDIS_URL=redis://lolipop:SOME_PASSWORD#dokku-redis-lolipop:6379
NOTE: the host exposed here only works internally in docker containers. If
you want your container to be reachable from outside, you should use 'expose'.
------------------------------
Edit - sorry, I forgot to add that I have tried process.env
How did you link the redis service with your application? You cannot simply do dokku config:set, and if you did, you should unset it and then use dokku redis:link instead. Once you do that, rebuild your app using dokku ps:rebuild APP and you should get process.env.REDIS_URL set.
you can access environment variables through process.env like the following:
console.log(process.env["DOKKU_REDIS_LOLIPOP_NAME"]);
console.log(process.env["DOKKU_REDIS_LOLIPOP_PORT"]);
console.log(process.env["REDIS_URL"]);
also as long as keys in objects do not harm variable naming conventions you can access them like this too:
console.log(process.env.REDIS_URL);
more info in regards to javascript variable naming rules: What characters are valid for JavaScript variable names?

Automatic way to pick up the hostname inside docker container

We're running NodeJS application inside docker container hosted on Amazon EC2 instance. To
To enable Monitoring for Node.js app with Datadog we are using datadog-metrics library and integrate it with our application. We basically require to save the below Javascript code into a file called example_app.js
var metrics = require('datadog-metrics');
metrics.init({ **host: 'myhost', prefix: 'myapp.'** });
function collectMemoryStats() {
var memUsage = process.memoryUsage();
metrics.gauge('memory.rss', memUsage.rss);
metrics.gauge('memory.heapTotal', memUsage.heapTotal);
metrics.gauge('memory.heapUsed', memUsage.heapUsed);
metrics.increment('memory.statsReported');
}
setInterval(collectMemoryStats, 5000);
Although, we are able to successfully publish metrics to datadog but we're wondering if this can be automated. We want build this into our docker image, hence require an automatic way to pick up the hostname, at the very least be able to use the docker hosts name if possible..Because till now we're manually specifying "myhost" and "myapp" values manually. Any better way to fetch the AWS instance hostname value into %myhost?
Why not try?
var os = require(“os”);
var hostname = os.hostname();
It will return the docker container's hostname. If you haven't set a hostname explicitly, using something like docker run -h hostname image command then it will return the docker host's hostname.
Alternatively, you could do this using a deployment tool like puppet, ansible, etc. and template the file when you deploy the container.

Update deployment via linux script in weblogic

What is the script to update deployment ( from GUI, we can do this update by unlock & save changes ) in linux. Is it possible to do this ? If not what is script to redeploy ?
As Kevin pointed out, WLST is the way to go. You should probably craft a script (named wlDeploy.py, for instance), with content like follows (import clauses were omitted for the sake of simplicity):
current_app_name = '[your current deployed app name]'
new_app_name = '[your new app name]'
target_name = '[WL managed server name (or AdminServer)]'
connect([username],[pwd],'t3://[admin server hostname/IP address]:[PORT]')
stopApplication(current_app_name)
undeploy(current_app_name, timeout=60000);
war_path = '[path to war file]'
deploy(appName=new_app_name, path=war_path, targets=target_name);
And call it via something like:
./wlst.sh wlDeploy.py
Of course you can add parameters to your script, and a lot of logic which is relevant to your deployment. This is entirely up to you. The example above, though, should help you getting started.
In WebLogic you can use wlst to perform administrative tasks like managing deployments. If you google weblogic wlst, you will receive tons of information. wlst runs on the python language.
Assuming you are using weblogic 10 you can also "Record" your actions. This will save the actions into a python script which you can "replay" (execute) later.

Resources