Cannot set dynamic template when posting to Cloud Dataflow template REST API - rest

I am trying to schedule a dataflow job with Cloud Scheduler by posting to REST API and authenticate by OAUTH. I have created a template and it works when I manually use Dataflow 'Create job from template'. However, when being used as a HTTP endpoint (https://dataflow.googleapis.com/v1b3/projects/${my.proj}/locations/europe-west1/templates:launch?gcsPath=gs://${my.proj}/templates/${template.name}), it returns the following error:
{
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"jobName\": Cannot bind query parameter. Field 'jobName' could not be found in request message.\nInvalid JSON payload received. Unknown name \"environment\": Cannot bind query parameter. Field 'environment' could not be found in request message.\nInvalid JSON payload received. Unknown name \"parameters\": Cannot bind query parameter. Field 'parameters' could not be found in request message.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"jobName\": Cannot bind query parameter. Field 'jobName' could not be found in request message."
},
{
"description": "Invalid JSON payload received. Unknown name \"environment\": Cannot bind query parameter. Field 'environment' could not be found in request message."
},
{
"description": "Invalid JSON payload received. Unknown name \"parameters\": Cannot bind query parameter. Field 'parameters' could not be found in request message."
}
]
}
]
}
}
Following is my POST body:
{
"jobName": "test",
"parameters": {
"region": "europe-west1"
},
"environment": {
"tempLocation": "gs://${my.proj}/temp",
"zone": "europe-west1"
}
}
I appreciate any help, thank you in advance!!

I verified that below works:
TEMPLATE_LOCATION="gs://${my.proj}/templates/${template.name}"
API_ROOT_URL="https://dataflow.googleapis.com/"
TEMPLATES_LAUNCH_API="${API_ROOT_URL}/v1b3/projects/${my.proj}/locations/europe-west1/templates:launch"
time curl -X POST -H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"${TEMPLATES_LAUNCH_API}"`
`"?gcsPath=${TEMPLATE_LOCATION}"`
` -d '
{
"jobName": "test",
"parameters": {},
"environment": {
"tempLocation": "gs://${my.proj}/temp",
"workerZone": "europe-west1-d",
}
}'
Note that you don't need to specify region in parameters, and it's workerZone instead of zone.

Related

PUT k8s deployment returns 404

According to the Replacement section of Kubernetes API reference v1.24 I should be able to create a deployment with a PUT /apis/apps/v1/namespaces/{namespace}/deployments/{name} HTTP request. The success response here is 201 Created. However, when I try the following, I get a 404 Not Found which is of course correct but unwanted: PUT requests should be treated as Create statements if the resource does not yet exist as documented. Updating a deployment does work (and returns the expected 200 OK HTTP response). Is there any documentation regarding this? Or is the request somehow incorrect? Ty.
➜ ~ curl --request PUT \
--url http://localhost:8080/apis/apps/v1/namespaces/ns/deployments/nginx-deployment \
--header 'content-type: application/json' \
--data '{
"apiVersion":"apps/v1",
"kind":"Deployment",
"metadata":{
"name":"nginx-deployment",
"labels":{
"app":"nginx"
}
},
"spec": {
"replicas" : 3,
"selector": {
"matchLabels" : {
"app":"nginx"
}
},
"template" : {
"metadata" : {
"labels" : {
"app":"nginx"
}
},
"spec":{
"containers":[
{
"name":"ngnix",
"image":"nginx:1.7.9",
"ports":[
{
"containerPort": 80
}
]
}
]
}
}
}
}'
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "deployments.apps \"nginx-deployment\" not found",
"reason": "NotFound",
"details": {
"name": "nginx-deployment",
"group": "apps",
"kind": "deployments"
},
"code": 404
}%
According to the documentation you provided,
PUT /apis/apps/v1/namespaces/{namespace}/deployments/{name}
is meant to "replace the specified Deployment", while a Deployment is created with a POST:
create a Deployment
HTTP Request
POST /apis/apps/v1/namespaces/{namespace}/deployments
You are correct that the documentation also states:
For PUT requests, Kubernetes internally classifies these as either create or update based on the state of the existing object
so there seems to be a contradiction, but the Deployment API spec states that POST should be used to create a deployment and PUT to update it.

Using REST API to create alerting rule in Kibana fails on 400 "Invalid action groups: default"

I have ELK cloud v. 7.13.2 and trying to create alert rule with slack action via REST API. This is my curl invocation:
curl -u ****** -s -H 'kbn-xsrf: true' -H 'Content-Type: application/json' https://***********.westeurope.azure.elastic-cloud.com:9243/api/alerting/rule -X POST -d #src/rules/cpu_utilization.json
I am expecting that new rule is created, but unfortunately I am getting following error:
{
"statusCode": 400,
"error": "Bad Request",
"message": "Invalid action groups: default"
}
The contents of src/rules/cpu_utilization.json are:
{
"params": {
"nodeType": "host",
"criteria": [
{
"comparator": ">",
"timeSize": 1,
"metric": "cpu",
"threshold": [
80
],
"timeUnit": "m"
}
],
"sourceId": "default"
},
"consumer": "alerts",
"schedule": {
"interval": "1m"
},
"tags": [],
"name": "CPU2",
"throttle": "1000d",
"enabled": true,
"rule_type_id": "metrics.alert.inventory.threshold",
"notify_when": "onThrottleInterval",
"actions": [
{
"group": "default",
"id": "fce4c27f-d22a-4209-858c-253a06511c1b",
"params": {
"message": "{{alertName}} - {{context.group}} is in a state of {{context.alertState}}\n\nReason:\n{{context.reason}}"
}
}
]
}
Documentation says clearly:
Properties of the action objects:
group
(Required, string) Grouping actions is recommended for escalations for different types of alerts. If you don’t need this, set this value to default.
Is this a bug in ELK or I am doing something wrong? I am able to use API for other purposes, like listing rules, deleting rules etc. I am also capable of creating a rule without an action, but this doen`t seem to be too useful...
OKAY, I got an answer from ELK support. Apparently, you can use another endpoint to list all rule types GET /api/alerting/rule_types. Then you need to find your type and lookup property default_action_group_id - it will hold the correct value. Eg. in the above example it was:
"default_action_group_id": "metrics.inventory_threshold.fired"

Artemis jolokia rest api returns no real data (Jsr160ProxyNotEnabledByDefaultAnymoreDispatcher)

I've an Artemis Broker (2.17) running on my dev machine for local testing.
From the web-console I've extractet the request to get the names of all queues.
When I execute the request from the browser console i get a JSON result like this:
{
"request": {
"mbean": "org.apache.activemq.artemis:broker=\"MyBroker\"",
"arguments": [
"ANYCAST"
],
"type": "exec",
"operation": "getQueueNames(java.lang.String)"
},
"value": [
"DLQ",
"ExpiryQueue"
],
"timestamp": 1624274952,
"status": 200
}
When I execute the same request from my code I get a very different result:
{
"request": {
"type": "version"
},
"value": {
"agent": "1.6.2",
"protocol": "7.2",
"config": {
"listenForHttpService": "true",
"authIgnoreCerts": "false",
"agentId": "192.168.1.41-30064-15b82644-servlet",
"debug": "false",
"agentType": "servlet",
"policyLocation": "file:/C:/Artemis/MyBroker/etc//jolokia-access.xml",
"agentContext": "/jolokia",
"serializeException": "false",
"mimeType": "text/plain",
"dispatcherClasses": "org.jolokia.http.Jsr160ProxyNotEnabledByDefaultAnymoreDispatcher",
"authMode": "basic",
"authMatch": "any",
"streaming": "true",
"canonicalNaming": "true",
"historyMaxEntries": "10",
"allowErrorDetails": "false",
"allowDnsReverseLookup": "true",
"realm": "jolokia",
"includeStackTrace": "false",
"mbeanQualifier": "qualifier=hawtio",
"useRestrictorService": "false",
"debugMaxEntries": "100"
},
"info": {
"product": "jetty",
"vendor": "Eclipse",
"version": "9.4.27.v20200227"
}
},
"timestamp": 1624274809,
"status": 200
}
Jsr160ProxyNotEnabledByDefaultAnymoreDispatcher seams very strange. But when searching for this name I couldn't realy find anything usefull. Also I cannot find any usefull information in the Artemis logs.
Here is my code:
using System;
using System.Net.Http;
using System.Text;
using System.Threading;
const String username = "admin";
const String password = "password";
var encoded = Convert.ToBase64String( Encoding.GetEncoding( "ISO-8859-1" )
.GetBytes( username + ":" + password ) );
var url = "http://localhost:8161/console/jolokia/?maxDepth=7&maxCollectionSize=50000&ignoreErrors=true&canonicalNaming=false";
var http = new HttpClient();
http.BaseAddress = new("http://localhost:8161/");
http.DefaultRequestHeaders.Add( "Authorization", "Basic " + encoded );
http.DefaultRequestHeaders.Add( "Origin", "http://localhost:8161/" );
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new(url),
Content = new StringContent( "{\"type\":\"exec\",\"mbean\":\"org.apache.activemq.artemis:broker=\\\"MyBroker\\\"\",\"operation\":\"getQueueNames(java.lang.String)\",\"arguments\":[\"ANYCAST\"]}" )
};
request.Content.Headers.ContentType = new("text/json");
var response = await http.SendAsync( request, HttpCompletionOption.ResponseHeadersRead, CancellationToken.None );
if ( response.IsSuccessStatusCode )
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine( content );
}
else
Console.WriteLine( "Request failed...." );
Console.ReadLine();
In the bootstrap.xml the binding is set to 0.0.0.0 which should be ok.
jolokia-access.xml contained <allow-origin>*://localhost*</allow-origin> which should be fine but just to be sure I've replaced it with <allow-origin>*</allow-origin>
Is there something I need to configure to make this work?
Jolokia requests can be sent in two ways: Either as a HTTP GET request, in which case the request parameters are encoded completely in the URL. Or as a POST request where the request is put into a JSON payload in the HTTP request's body. See the Jolokia Protocol for further details.
When the Jolokia service doesn't get any request it will answer with service information, ie:
{
"request": {
"type": "version"
},
"value": {
...
To request the queue names using an HTTP GET request
curl -H "Origin:http://localhost:8161" -u admin:admin http://localhost:8161/console/jolokia/exec/org.apache.activemq.artemis:broker=\"MyBroker\"/getQueueNames/ANYCAST
To request the queue names using an HTTP POST request
curl -X POST -H "Content-Type: application/json" -H "Origin:http://localhost:8161" -u admin:admin http://localhost:8161/console/jolokia -d '{"type" : "EXEC", "mbean" : "org.apache.activemq.artemis:broker=\"MyBroker\"", "operation" : "getQueueNames", "arguments" : ["ANYCAST"]}'
Your code is using an HTTP GET, but it is using a fixed URL (i.e. http://localhost:8161/console/jolokia/?maxDepth=7&maxCollectionSize=50000&ignoreErrors=true&canonicalNaming=false and a payload (i.e. {"type":"exec","mbean":"org.apache.activemq.artemis:broker="MyBroker","operation":"getQueueNames(java.lang.String)","arguments":["ANYCAST"]}"). This does not conform with the Jolokia protocol.
If you use an HTTP GET then everything should be in the URL itself presumably just like it was your browser console. For example, use this:
http://localhost:8161/console/jolokia/exec/org.apache.activemq.artemis:broker="MyBroker"/getQueueNames/ANYCAST

How do I use Marketo REST API with Postman?

I'm having a hard time trying to figure out how to properly use the Marketo REST API using Postman for testing purpose.
So far I can Authenticate and get my access_token,
but when I try to create a folder... (properly authenticated)
endpoint: [POST] /rest/asset/v1/folders.json
body:
{
"description": "Test Folder",
"name": "Test",
"parent": {
"id": 1,
"type": "Folder"
}
}
I get:
{
"success": false,
"errors": [
{
"message": "name cannot be null.",
"code": "701"
},
{
"message": "parent cannot be null",
"code": "701"
}
],
"requestId": "408a#1720c00a893",
"warnings": []
}
I don't know what I'm doing wrong.
See an example in the Marketo API documentation
Create/Update folder request should be an application/x-www-form-urlencoded not application/json
So in Postman, you have to post a form with three parameters:
parent={"id":416,"type":"Folder"}
name=Test 10 - deverly
description=This is a test
For the parent parameter you should specify a specific json-like text, which is a usual format for folderId
For generic folders (not programs) you can provide just integer id, without JSON structure, this is not recommended but can be used for manual API tests

FireStore REST API: How to add a subcollection to a document using REST commands?

Using FireStore's REST API documented at: https://firebase.google.com/docs/firestore/reference/rest
I'm trying to create a new document in "users" that has a subcollection named "subcol1" with an empty doc in it called "subdoc1"
However, the following REST command to create the new document does not work:
curl -X POST
-H "Content-Type: application/json"
-d "{ 'fields': { 'subcol1': [{'subdoc1': { 'fields': {} } }] } }"
"https://firestore.googleapis.com/v1/projects/XXXX/databases/(default)/documents/users"
How does one add a subcollection to a new document (or existing one?) using FireStore's REST API?
I specifically have to use REST for this implementation.
This is the error response I get back:
{ "error": {
"code": 400,
"message": "Invalid value at 'document.fields[0].value' (Map), Cannot have repeated items ('subcol1') within a map.\nInvalid JSON payload received. Unknown name \"\" at 'document.fields[0].value': Proto fields must have a name.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "document.fields[0].value",
"description": "Invalid value at 'document.fields[0].value' (Map), Cannot have repeated items ('subcol1') within a map."
},
{
"field": "document.fields[0].value",
"description": "Invalid JSON payload received. Unknown name \"\" at 'document.fields[0].value': Proto fields must have a name."
}
]
}
] } }
Thanks!
After more tinkering with this, I found a solution.
The following works:
First create the new document (without the subcollection).
Next create the subdocument using the "not-yet-created" subcollection's URL.
So first create the new "top-level" doc:
curl -X POST
-H "Content-Type: application/json"
-d "{ 'fields': { } }"
"https://firestore.googleapis.com/v1/projects/XXXX/databases/(default)/documents/users"
Then create the subdoc (which "creates" the subcollection):
curl -X POST
-H "Content-Type: application/json"
-d "{ 'fields': { } }"
"https://firestore.googleapis.com/v1/projects/XXXX/databases/(default)/documents/
users/<USER-KEY-FROM-PREVIOUS-JSON-RESPONSE>/subcol1"