SeldonIO | sklearn_iris and sklearn_spacy_text | not working in k8s - kubernetes

Ref:
https://github.com/SeldonIO/seldon-core/blob/master/examples/models/sklearn_iris/sklearn_iris.ipynb
https://github.com/SeldonIO/seldon-core/tree/master/examples/models/sklearn_spacy_text
#Steps Done
1. kubectl port-forward $(kubectl get pods -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].metadata.name}') -n istio-system 8003:80
2.kubectl create namespace john
3.kubectl config set-context $(kubectl config current-context) --namespace=john
4.kubectl create -f sklearn_iris_deployment.yaml
cat sklearn_iris_deployment.yaml
apiVersion: machinelearning.seldon.io/v1alpha2
kind: SeldonDeployment
metadata:
name: seldon-deployment-example
namespace: john
spec:
name: sklearn-iris-deployment
predictors:
- componentSpecs:
- spec:
containers:
- image: seldonio/sklearn-iris:0.1
imagePullPolicy: IfNotPresent
name: sklearn-iris-classifier
graph:
children: []
endpoint:
type: REST
name: sklearn-iris-classifier
type: MODEL
name: sklearn-iris-predictor
replicas: 1
kubectl get sdep -n john seldon-deployment-example -o json | jq .status
"deploymentStatus": {
"sklearn-iris-deployment-sklearn-iris-predictor-0e43a2c": {
"availableReplicas": 1,
"replicas": 1
}
},
"serviceStatus": {
"seldon-635d389a05411932517447289ce51cde": {
"httpEndpoint": "seldon-635d389a05411932517447289ce51cde.john:9000",
"svcName": "seldon-635d389a05411932517447289ce51cde"
},
"seldon-bb8b177b8ec556810898594b27b5ec16": {
"grpcEndpoint": "seldon-bb8b177b8ec556810898594b27b5ec16.john:5001",
"httpEndpoint": "seldon-bb8b177b8ec556810898594b27b5ec16.john:8000",
"svcName": "seldon-bb8b177b8ec556810898594b27b5ec16"
}
},
"state": "Available"
}
5.here iam using istio and as per this doc https://docs.seldon.io/projects/seldon-core/en/v1.1.0/workflow/serving.html i did the same
Istio
Istio REST
Assuming the istio gateway is at <istioGateway> and with a Seldon deployment name <deploymentName> in namespace <namespace>:
A REST endpoint will be exposed at : http://<istioGateway>/seldon/<namespace>/<deploymentName>/api/v1.0/predictions
curl -s http://localhost:8003/seldon/john/sklearn-iris-deployment-sklearn-iris-predictor-0e43a2c/api/v0.1/predictions -H "Content-Type: application/json" -d '{"data":{"ndarray":[[5.964,4.006,2.081,1.031]]}}' -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8003 (#0)
> POST /seldon/johnson-az-videspan/sklearn-iris-deployment-sklearn-iris-predictor-0e43a2c/api/v0.1/predictions HTTP/1.1
> Host: localhost:8003
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 48
>
* upload completely sent off: 48 out of 48 bytes
< HTTP/1.1 301 Moved Permanently
< location: https://localhost:8003/seldon/john/sklearn-iris-deployment-sklearn-iris-predictor-0e43a2c/api/v0.1/predictions
< date: Fri, 23 Oct 2020 13:09:46 GMT
< server: istio-envoy
< connection: close
< content-length: 0
<
* Closing connection 0
the same thing happen in sklearn_spacy_text model too but i wonder the same models working perfectly while running it on docker.
please find the sample responce from docker
curl -s http://localhost:5000/predict -H "Content-Type: application/json" -d '{"data":{"ndarray":[[5.964,4.006,2.081,1.031]]}}' -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 5000 (#0)
> POST /predict HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.61.1
> Accept: */*
> Content-Type: application/json
> Content-Length: 48
>
* upload completely sent off: 48 out of 48 bytes
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: application/json
< Content-Length: 125
< Access-Control-Allow-Origin: *
< Server: Werkzeug/1.0.0 Python/3.7.4
< Date: Fri, 23 Oct 2020 11:18:31 GMT
<
{"data":{"names":["t:0","t:1","t:2"],"ndarray":[[0.9548873249364169,0.04505474761561406,5.7927447968952436e-05]]},"meta":{}}
* Closing connection 0
curl -s http://localhost:5001/predict -H "Content-Type: application/json" -d '{"data": {"names": ["text"], "ndarray": ["Hello world this is a test"]}}'
{"data":{"names":["t:0","t:1"],"ndarray":[[0.6811839197596743,0.3188160802403257]]},"meta":{}}
can any one help to resolve this issue

Issue
It appears that the request you make incorrectly tries to re-direct to an https protocol (port 443)
Solution
Use https instead of http
curl -s https://localhost:8003/seldon/john/sklearn-iris-deployment-sklearn-iris-predictor-0e43a2c/api/v0.1/predictions -H "Content-Type: application/json" -d '{"data":{"ndarray":[[5.964,4.006,2.081,1.031]]}}' -v
Use curl with -L flag, which instructs curl to follow redirects. In this case, the server returned a redirect response (301 Moved Permanently) for the HTTP request to http://localhost:8003. The redirect response instructs the client to send an additional request, this time using HTTPS, to https://localhost:8003.
More about it here.

Related

Call api with curl and TLS 1.2 Two Way with public certificates of entities

I am currently calling a service which requires mutual authentication with curl and ubuntu, currently
I have the following certificates certRoot.cer, certSub.cer, domain.com.cer and pubkey.pem, to add the certificates to the path /etc/ssl/certs/ca-certificates.crt transform them all to a format pem and i made the call:
curl -v \
--key /etc/ssl/certs/ca-certificates.crt \
-u "user:password" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data-raw '{"info":"data"}' \
https://endpoint.com:4445/api/path
This call itself is correct and returns the following information:
* Trying ip...
* Connected to endpoint.com (ip) port 4445 (#0)
* found 136 certificates in /etc/ssl/certs/ca-certificates.crt
* found 536 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_256_GCM_SHA384
* server certificate verification OK
* server certificate status verification SKIPPED
* common name: endpoint.com (matched)
* server certificate expiration date OK
* server certificate activation date OK
* certificate public key: RSA
* certificate version: #3
* subject: C=CO,ST=STATE,L=DATA,O=DATA,OU=Sistemas,CN=endpoint.com
* start date: Tue, 03 Sep 2019 14:42:57 GMT
* expire date: Thu, 02 Sep 2021 14:42:57 GMT
* issuer: C=CO,ST=DATA,L=DATA,L=ADDRESS,O=DATA,OU=Gerencia de Sistemas,CN=DATA Sub CA Terceros
* compression: NULL
* ALPN, server did not agree to a protocol
* Server auth using Basic with user 'user'
> POST api/path HTTP/1.1
> Host: endpoint.com:4445
> Authorization: Basic dXNycHJ1X2Jpb2NyZWRpdDpQc123YmExMjM7
> User-Agent: curl/7.47.0
> Accept: application/json
> Content-Type: application/json
> Content-Length: 920
>
* upload completely sent off: 920 out of 920 bytes
< HTTP/1.1 403 Forbidden
< Date: Tue, 06 Apr 2021 21:37:21 GMT
< Strict-Transport-Security: max-age=31536000; includeSubDomains
< Content-Security-Policy: frame-ancestors 'none'
< Content-Length: 234
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /api/path
on this server.</p>
</body></html>
* Connection #0 to host endpoint.com left intact
but at the moment in which the call is verified from the api side, it indicates that the certificate was not sent and rejects the connection, I imagine that is why it returns the error 403 (forbidden).
I have also tried to do it by passing the certificates directly, but it returns this error:
curl -v \
--key pubkey.pem \
--cert domain.com.cer \
-u "user:password" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data-raw '{"info":"data"}' \
https://endpoint.com:4445/api/path
In this case the answer is the following:
* Trying ip...
* Connected to domain.com (ip) port 4445 (#0)
* found 136 certificates in /etc/ssl/certs/ca-certificates.crt
* found 536 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* error reading X.509 key or certificate file: Error in parsing.
* Closing connection 0
curl: (35) error reading X.509 key or certificate file: Error in parsing.
I clarify that all this also happens through a vpn and the connection to this vpn is already ok, if anyone has any idea how I can solve this problem I thank you very much, it can be with using any language or terminal client.
To complete this call successfully I did it with python, then I leave the code that I use:
import socket
import ssl
host_addr = 'domain.com'
host_port = 4445
server_sni_hostname = 'domain.com'
server_cert = '../DESTINATION.cer' #CERTIFICATE OF DESTINATION, IN PEM FORMAT ( -----BEGIN CERTIFICATE----- ...... -----END CERTIFICATE----- )
client_cert = '../CUSTOMER_CERTIFICATE.cer' #CUSTOMER CERTIFICATE, IN PEM FORMAT ( -----BEGIN CERTIFICATE----- ...... -----END CERTIFICATE----- )
client_key = '../CUSTOMER_PRIVATE_KEY.key' #CUSTOMER PRIVATE KEY, IN PEM AND PKCS8 FORMAT (-----BEGIN PRIVATE KEY----- ....... -----END PRIVATE KEY-----)
basicAuthHeader = 'dXNlcjpwYXNzd29yZA==' #USER:PASSWORD >> BASE64
method = 'POST /path/of/service HTTP/1.1\r\n'
headers = 'Host:'+host_addr+'\r\nContent-Type:application/json\r\nAuthorization:'+basicAuthHeader+'\r\nAccept:application/json\r\n\r\n'
body = '{"data":"string","data1":"string","data2":"string","data3":"string","data4":"string"}'
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile=server_cert)
context.load_cert_chain(certfile=client_cert, keyfile=client_key)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn = context.wrap_socket(s, server_side=False, server_hostname=server_sni_hostname)
conn.connect((host_addr, host_port))
print("SSL established. ")
print("Sending:")
conn.send(bytes(method+headers+body, 'utf-8'))
print("Receiving")
received = conn.recv(36000)
print(received)
print("Closing connection")
conn.close()
I hope it will be of help to you in the future, for me it was a long task until I reached the solution.

Does jetty overwrite custom http status code ?

I am trying to develop a rest api for my service wherein I set custom http status code depending on authorisation failure. But when I test it out using curl I am receiving 404 instead of 403. I am perplexed as to what might be causing this? Please help.
This is what I see from curl output or swagger UI:
root#ubuntu:~# curl -X GET http://localhost:8082/mr/v1/topic/bhakk -v
Note: Unnecessary use of -X or --request, GET is already inferred.
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8082 (#0)
> GET /mr/v1/topic/bhakk HTTP/1.1
> Host: localhost:8082
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Mon, 07 May 2018 22:00:10 GMT
< Exception: serviceBlockedException
< Content-Type: application/vnd.kafka.v1+json
< Content-Length: 83
< Server: Jetty(9.2.z-SNAPSHOT)
<
* Connection #0 to host localhost left intact
{"error_code":40301,"message":"This service does not have access to the resource."}
Here is the code:
public Collection<String> list(#HeaderParam("x-nssvc-serviceid") String serviceID) {
Date now = new java.util.Date();
if (! ctx.getSecurityRestrictions().isServiceAllowed(uri, httpHeaders, "Describe", "Cluster", "kafka-cluster"))
throw Errors.serviceBlockedException(ctx,httpServletResponse);
List<String> topicsCopy = new ArrayList<String>(topics);
for (Iterator<String> iterator = topicsCopy.iterator(); iterator.hasNext();) {
String topic = iterator.next();
if (! ctx.getSecurityRestrictions().hasAccess (serviceId, "Describe", "Topic", topic)) {
iterator.remove();
}
}
return topicsCopy;
}
public static RestException serviceBlockedException(Context ctx,HttpServletResponse httpServletResponse) {
httpServletResponse.setHeader("Exception","serviceBlockedException");
httpServletResponse.setStatus(Status.FORBIDDEN.getStatusCode()); <----// here i am setting status code.
return new RestNotFoundException(SERVICE_ID_BLOCKED_MESSAGE, SERVICE_ID_BLOCKED_ERROR_CODE);
}
Kafka sets the Response 404 status in its RestNotFoundException
See: https://github.com/confluentinc/rest-utils/blob/master/core/src/main/java/io/confluent/rest/exceptions/RestNotFoundException.java

play scala 2.4.3 redicrect not working

I'm trying the Reverse routing sample code
Here are my routes
GET /hello/:name controllers.Application.hello(name)
GET /bob controllers.Application.helloBob
and my codes
def helloBob = Action {
Redirect(routes.Application.hello("Bob"))
}
def hello(name: String) = Action {
Ok("Hello " + name + "!")
}
I can get hello response
$ curl -v localhost:9001/hello/play
Hello play!
But, can't get "Bob" response after redirect?
$ curl -v localhost:9001/bob
* Trying ::1...
* Connected to localhost (::1) port 9001 (#0)
> GET /bob HTTP/1.1
> Host: localhost:9001
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 303 See Other
< Location: /hello/Bob
< Date: Fri, 18 Sep 2015 03:19:04 GMT
< Content-Length: 0
<
* Connection #0 to host localhost left intact
The path component of a URI is case sensitive. Check it.
try
curl -v localhost:9001/hello/Bob
Update
You code is correct (verified on my project) and you show the correct log - it prints 303 code. I think, you just need to say curl to follow redirect, like this
curl -L localhost:9000/bob

REST interface using nginx httpluamodule

I'm just getting started with nginx and the HttpLuaModule. I've created a test configuration file to familiarize myself with how things work.
now I'm trying to write some logic to accept GET, POST and DELETE requests for a specific type of resource.
I would like to create a "location" entry that would match the following URI / accept the following curl calls:
curl -i -X GET http://localhost/widgets/widget?name=testname&loc=20000 -H "Accept:application/json"
This is what my current nginx.conf looks like:
server {
listen 80;
server_name nsps2;
root /var/www/;
index index.html index.htm;
#charset koi8-r;
#access_log logs/host.access.log main;
#curl http://localhost/hello?name=johndoe
location /hello {
default_type "text/plain";
content_by_lua '
local rquri = ngx.var.request_uri;
ngx.say("the uri is ", rquri ,".")
local name = ngx.var.arg_name or "Anonymous"
ngx.say("Hello, ", name, "!")
';
}
location / {
root /var/www/;
index index.html index.htm;
}
#curl -i -X GET http://localhost/widgets/widget?name=testname&loc=20000 -H "Accept:application/json"
location /widgets/widget {
root /var/www/widgets;
default_type "text/pain";
content_by_lua '
local arga,argb = ngx.arg[1], ngx.arg[2] ;
ngx.say("the arga is ", arga ,".")
ngx.say("the argb is ", argb, ".")
';
}
Using the last "location" entry, I'm trying to
1. prove that the system is getting the GET request
2. prove that I understand how to access the parameters passed in with the GET request.
I'm getting an error right now that looks like this:
2015/02/24 20:18:19 [error] 2354#0: *1 lua entry thread aborted: runtime error: content_by_lua:2: API disabled in the context of content_by_lua*
stack traceback:
coroutine 0:
[C]: in function '__index'
content_by_lua:2: in function <content_by_lua:1>, client: 127.0.0.1, server: nsps2, request: "GET /widgets/widget?name=testname?loc=20000 HTTP/1.1", host: "localhost"
I'm not too sure about what this error means / is trying to tell me.
Any tips would be appreciated.
Thank you.
EDIT 1
I think the problem was something syntactically wrong. I was reading the manual and found an example to try. I've changed the code to look like this:
location /widgets/widget {
default_type "text/pain";
content_by_lua '
local args = ngx.req.get_uri_args()
for key, val in pairs(args) do
if type(val) == "table" then
ngx.say(key, ": ", table.concat(val, ", "))
else
ngx.say(key, ": ", val)
end
end
';
}
Now when I call the app like this:
mytestdevbox2:/var/www/nsps2# curl -i -X GET http://localhost/widgets/widget?name=testname&loc=20000 -H "Accept:application/json"
-ash: -H: not found
mytestdevbox2:/var/www/nsps2# HTTP/1.1 200 OK
Server: nginx/1.6.2
Date: Tue, 24 Feb 2015 21:32:44 GMT
Content-Type: text/pain
Transfer-Encoding: chunked
Connection: keep-alive
name: testname
[1]+ Done curl -i -X GET http://localhost/widgets/widget?name=testname
After the system displays the "name: testname" stuff, it just sits there until I hit "enter". After I do that, then it proceeds to display the 1+ stuff.
I'm not too sure what it's doing.
EDIT 2:
Adding quotes to the curl call did fix the problem:
mytestdevbox2:/var/www/nsps2# curl -i -X GET 'http://localhost/widgets/widget?name=testname&loc=20000'
HTTP/1.1 200 OK
Server: nginx/1.6.2
Date: Wed, 25 Feb 2015 12:59:29 GMT
Content-Type: text/pain
Transfer-Encoding: chunked
Connection: keep-alive
loc: 20000
name: testname
mytestdevbox2:/var/www/nsps2#
The problem described in EDIT 1 doesn't have anything to do with your question about nginx and is caused by not quoting the parameters for curl when you execute the command:
curl -i -X GET http://localhost/widgets/widget?name=testname&loc=20000
This is executed as two commands separated by '&': curl -i -X GET http://localhost/widgets/widget?name=testname and loc=20000; that's why you see the output after you already got the prompt back as the first command is now executed in the background. "1+ Done" message is a confirmation that the background process is terminated; it's just shown after you press Enter.
Wrap the URL with the query string in quotes and you should see the expected behavior.

REST API returning an AUTHORIZATION_ERROR

Following some of the examples provided in the Invoicing REST API https://developer.paypal.com/docs/api/#invoicing I am always receiving an AUTHORIZATION_ERROR.
Here is an example:
First retrieving my token:
curl https://api.sandbox.paypal.com/v1/oauth2/token \
> -H "Accept: application/json" \
> -H "Accept-Language: en_US" \
> -u "AbNzCxxxxs6iVF0:EBhQWxxxxxxrgefvhb" \
> -d "grant_type=client_credentials"
{"scope":"openid https://uri.paypal.com/services/invoicing https://api.paypal.com/v1/payments/.* https://api.paypal.com/v1/vault/credit-card/.* https://api.paypal.com/v1/vault/credit-card","access_token":"F9Ig.4FXq1DQICPrMaUUb0-K--3dWBHvqRck636df4A","token_type":"Bearer","app_id":"APP-80W284485P519543T","expires_in":28800}%
Then using that token to create an invoice:
curl -v -X 'POST' 'https://api.sandbox.paypal.com/v1/invoicing/invoices' \
> -H 'Content-Type: application/json' \
> -H 'Authorization: Bearer F9Ig.4FXq1DQICPrMaUUb0-K--3dWBHvqRck636df4A' \
> -d '{
quote> "merchant_info": {
quote> "email": "rdg#rapiddg.com",
quote> "first_name": "Mike",
quote> "last_name": "Bopp",
quote> "business_name": "RDG",
quote> "phone": {
quote> "country_code": "001",
quote> "national_number": "5032141716"
quote> },
quote> "address": {
quote> "line1": "1234 Main St.",
quote> "city": "Portland",
quote> "state": "OR",
quote> "postal_code": "97217",
quote> "country_code": "US"
quote> }
quote> }
quote> }'
* Adding handle: conn: 0x7ff110804000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7ff110804000) send_pipe: 1, recv_pipe: 0
* About to connect() to api.sandbox.paypal.com port 443 (#0)
* Trying 23.52.155.39...
* Connected to api.sandbox.paypal.com (23.52.155.39) port 443 (#0)
* TLS 1.2 connection using TLS_RSA_WITH_RC4_128_SHA
* Server certificate: api.sandbox.paypal.com
* Server certificate: VeriSign Class 3 Secure Server CA - G3
* Server certificate: VeriSign Class 3 Public Primary Certification Authority - G5
* Server certificate: Class 3 Public Primary Certification Authority - G2
> POST /v1/invoicing/invoices HTTP/1.1
> User-Agent: curl/7.30.0
> Host: api.sandbox.paypal.com
> Accept: */*
> Content-Type: application/json
> Authorization: Bearer F9Ig.4FXq1DQICPrMaUUb0-K--3dWBHvqRck636df4A
> Content-Length: 387
>
* upload completely sent off: 387 out of 387 bytes
< HTTP/1.1 401 Unauthorized
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< PROXY_SERVER_INFO: host=slcsbjava3.slc.paypal.com;threadId=220
< Paypal-Debug-Id: 0329fb0c0e560
< WWW-Authenticate: OAuth
< Content-Type: application/json
< DC: origin2-api.sandbox.paypal.com
< Date: Fri, 02 May 2014 15:31:53 GMT
< Connection: close
< Set-Cookie: DC=origin2-api.sandbox.paypal.com; secure
<
* Closing connection 0
{"name":"AUTHORIZATION_ERROR","message":"Authorization error occurred.","debug_id":"0329fb0c0e560"}%
I can successfully send a payment request as is done here: https://developer.paypal.com/docs/integration/direct/make-your-first-call/
But for some reason the Invoice does NOT work.
I have verified that in my sandbox app I have enabled invoicing
Any help appreciated, thanks in advance.
Please change the email address(rdg#rapiddg.com) to the one that linked to the app you created before.
Please go ahead to check the email address in your REST APP.