Ignition and (Docker) Portainer API. (HTTP queries)

Has anyone had any luck with Ignition and portainer API?

I have been trying to connect to the Portainer API, with no luck. I have never used HTTP bindings before(which might be my real problem here).

The procedure for the portainer API should be quite simple:
https://gist.github.com/deviantony/77026d402366b4b43fa5918d41bc42f8

Http bindings aren’t going to work well for this purpose - they’re not very good at authentication right now.
I’d recommend system.net.httpClient(). You could wrap things in a class to make accessing the API a little friendlier:

class PortainerClient(object):
	def __init__(self, baseUrl, username, password, **kwargs):
		self.baseUrl = baseUrl
		self.client = system.net.httpClient(**kwargs)
		response = self.client.post(baseUrl + "auth", data={"Username": username, "Password": password})
		self.token = response.json["jwt"]
		
	def call(self, endpoint, method="GET", **kwargs):
		headers = kwargs.get("headers", {})
		headers["Authorization"] = "Bearer {}".format(self.token)
	
		response = self.client.request(self.baseUrl + endpoint, method, headers=headers, **kwargs)
		return response.json
		
client = PortainerClient("https://docker.ia.local/api/", "admin", "password", bypass_cert_validation=True)

print client.call("endpoints/1/docker/containers/json")
1 Like

That look very neat, I cant wait to thinker with that. Thanks alot @PGriffith !

I will post again when tested :slight_smile:

Works great!

How would you use this in perspective to show live status of containers(?):

I am thinking a gateway event timer script. Then write to a dataset tag. But then the script would init every time, which is unnecessary since the token is valid for 8 hours?

Parallel to the status being updated. If I make buttons in perspective to start/stop containers. Should I run this script directly, or use the already obtained token. In the latter case I must store the token somewhere; normal tag database, or session custom props?

I used a responsive view and made a (crude) interface:


Would be nice to get those state into the tag database for alarming though.

Maybe I will also add an interface for creating containers, maybe based on git repos.

1 Like

@PGriffith, do you have any idea why this wont work?

class PortainerClient(object):
	def __init__(self, baseUrl, username, password, **kwargs):
		self.baseUrl = baseUrl
		self.client = system.net.httpClient(**kwargs)
		response = self.client.post(baseUrl + "auth", data={"Username": username, "Password": password})
		self.token = response.json["jwt"]
		
	def call(self, endpoint, method="GET", **kwargs):
		headers = kwargs.get("headers", {})
		headers["Authorization"] = "Bearer {}".format(self.token)
	
		response = self.client.request(self.baseUrl + endpoint, method, headers=headers, **kwargs)
		return response.json
		
	def post(self, endpoint, **kwargs):
		headers = kwargs.get("headers", {})
		headers["Authorization"] = "Bearer {}".format(self.token)
		response=self.client.post(self.baseUrl + endpoint, headers=headers, **kwargs)
		print response
		return response.json


client = PortainerClient("http://MYIP:9000/api/", "admin", "password", bypass_cert_validation=True)

#create an exec instance
endpoint="endpoints/1/docker/containers/ba376d6b670b8aa946d1a26f28c781349be7b15753266aaf4dd78bcd85108dc5/exec"
data={ "AttachStdin":False,
"AttachStdout":True,
"AttachStderr":True, 
"Tty":False, 
"Cmd":['/bin/date'] }
returned=client.post(endpoint, data=data)

#Start the exec instance created above
endpoint="endpoints/1/docker/exec/"+str(returned['Id'])+"/start"
data = {"Detach": False,"Tty": False}
returned=client.post(endpoint,data=data)
print returned
print "\n"

I am always getting this error when running the last client.post()

Caused by: java.io.IOException: protocol error: Frame type(80) length(4740180) exceeds MAX_FRAME_SIZE(16384)


Try setting a -Djdk.httpclient.maxframesize=524288 in the JVM arguments of wherever you’re running the http client - if it’s on the gateway, it’ll be in ignition.conf, in the wrapper.java.additional parameters section.

Thanks, but i get exactly the same error.

I did like below, and rebooted the gateway. Im running in docker, but I guess it should not matter…

You mentioned where i run the http client, thats in the designer on a different computer. Where can I change the framesize for a client?

In the JVM arguments of the designer launcher configuration - the same argument without the wrapper.java.additional; the entire remainder of the line starting with -D should do it.