How to trigger pipeline API in AzureDevOps from Python (urllib3) - python

I have to trigger a pipeline in Azure DevOps from a python script. I have already found out that i need a private access token and that part is fine. I can, however, not get the script to work. I am trying something like this:
data = [
{
}
]
http = urllib3.PoolManager()
r = http.request('POST', api_url, headers={'Content-Type': 'application/json-patch+json', "Authorization": private_access_token}, body=data)
print(r.status)
print(r.data)
Its a requirement that i have to use urllib3 because I cant use the requests package
data is empty, because looking at the parameters here https://learn.microsoft.com/en-us/rest/api/azure/devops/pipelines/runs/run%20pipeline?view=azure-devops-rest-6.0. Then i dont need any input data? I just want to trigger a pipeline, nothing else
Error message is not very helpful. I get error message 203.

I solved it by using:
authorization = str(base64.b64encode(bytes(':'+private_access_token, 'ascii')), 'ascii')
data = {}
a = json.dumps(data)
http = urllib3.PoolManager()
r = http.request('POST', api_url, headers = {'Content-Type': 'application/json', 'Authorization': 'Basic '+authorization}, body=a)

Related

{'error': 'RESTEASY003650: No resource method found for PUT, return 405 with Allow header'} when updating user data in Keycloak

I am trying to update user info in keycloak by sending put request. Get request is working fine I am getting all the users but Whenever I tried to send put request to update the user data I get this error "{'error': 'RESTEASY003650: No resource method found for PUT, return 405 with Allow header'}" while searching for the solution I find somewhere that I should add 'HTTP_X_HTTP_METHOD_OVERRIDE' in headers I also tried this but still, I am facing same error, how can I fix it.
code:
def update_user(user_id, user_data):
import requests
headers = dict()
headers['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'
headers['content_type'] = 'application/json'
data = {
"grant_type": "password",
"username": "admin",
"password": os.getenv("KEYCLOAK_ADMIN_KEY"),
"client_id": "admin-cli"
}
token = _request("POST", f"{server_internal_url}realms/master/protocol/openid-connect/token", None, data=data).json()["access_token"]
# token = admin_token()
headers["Authorization"] = f"Bearer {token}"
headers["Host"] = kc_host
# here = _request("PUT", admin_url+f"/users"+"/".format(user_id=user_id), token, data=json.dumps(user_data)).json()
response = requests.put(admin_url+f"/users"+"/".format(user_id=user_id), headers=headers, data=data, verify=VERIFY)
print(response.json())
server_internal_url = "https://keycloak:8443/auth/"
admin_url = "https://keycloak:8443/auth/admin/realms/{realm_name}"
It looks like you request has wrong URL:
response = requests.put(admin_url+f"/users"+"/".format(user_id=user_id), headers=headers, data=data, verify=VERIFY)
I guess it should be:
response = requests.put(admin_url+"/users/"+user_id, headers=headers, data=data, verify=VERIFY)

Solution for the Invalid URL non-numeric port error?

I am trying to use a cryptcurrency API to get some information from a remote server in python. The example from the API how to do it is here: https://developers.cryptoapis.io/technical-documentation/blockchain-data/unified-endpoints/get-transaction-details-by-transaction-id
But when I try to run it I get an exception
Exception has occurred: InvalidURL
nonnumeric port: '//rest.cryptoapis.io/v2'
I am not sure what is wrong here (new to Python). Can someone please point out? I thought at least the formal example from the API provider must work?
My code is:
import http.client
conn = http.client.HTTPConnection("https://rest.cryptoapis.io/v2")
headers = {
'Content-Type': "application/json",
'X-API-Key': "API key provided by the software provider"
}
conn.request("GET", "blockchain-data,bitcoin,testnet,transactions,4b66461bf88b61e1e4326356534c135129defb504c7acb2fd6c92697d79eb250", headers=headers )
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
Looks like you misunderstood the documentation. You may find this helpful:-
import requests
import json
APIKEY = 'YourAPIKeyGoesHere' # <-----
BASE = 'https://rest.cryptoapis.io/v2'
BLOCKCHAIN = 'bitcoin'
NETWORK = 'testnet'
TID = '4b66461bf88b61e1e4326356534c135129defb504c7acb2fd6c92697d79eb250'
with requests.Session() as session:
h = {'Content-Type': 'application/json',
'X-API-KEY': APIKEY}
r = session.get(
f'{BASE}/blockchain-data/{BLOCKCHAIN}/{NETWORK}/transactions/{TID}', headers=h)
r.raise_for_status()
print(json.dumps(r.json(), indent=4, sort_keys=True))

Keep getting a 401 error when trying to pull data

I'm fairly new to using web APIs and pulling data and i'm also pretty new with python. My goal is to make a stat-tracker app but I keep getting a 401 when I try and pull the data.
I've printed out the entire url just to make sure I didn't get it wrong. I copied and pasted the API key exactly so that shouldn't be a problem
api_token = 'api key in python file'
api_url_base = 'https://public-api.tracker.gg/v2/apex/standard/'
headers = {'Content-Type' : 'application/json',
'Authorization' : 'Bearer {}'.format(api_token)}
def get_player_profile():
api_url = '{}profile/psn/Daltoosh'.format(api_url_base)
response = requests.get(api_url, headers=headers)
if response.status_code == 200:
return json.loads(response.content.decode('utf-8'))
else:
return response.status_code, api_url
print(get_player_profile())
#player_profile = get_player_profile()
#if player_profile is not None:
# print("Career Stats:")
# for k, v in player_profile['profile/psn/Daltoosh'].items():
# print('{0}:{1}.format(k, v)')
#else:
# print('[!] Data Request Failed [!]')
I expected a status code of 200 but there seems to be a problem authenticating.
I'm not too well versed in the web API that you are using, but I think you might be using the API token incorrectly. I don't think that specific API requires a Bearer token, but instead a separate header called TRN-Api-Key.
So maybe write something like this:
headers = {'Content-Type' : 'application/json', 'TRN-Api-Key' : api_token}
If you look here, you should be able to read up on how to set up authentication.

how to add authorization headers to bravado-created API client

I am able to create a simple API interface using the requests module that authenticates correctly and receives a response from an API. However, when I attempt to use bravado, to create the client from a swagger file, and manually add an authorization token to the head, it fails with :
bravado.exception.HTTPUnauthorized: 401 Unauthorized: Error(code=u'invalid_credentials', message=u'Missing authorization header',
I believe I am adding the authorization headers correctly.
The code I'm using to create the client is below. As shown, I've tried to add an Authorization token two ways:
in the http_client setup via set_api_key
in the Swagger.from_url(...) step by adding request_headers.
However both options fail.
from bravado.requests_client import RequestsClient
from bravado.client import SwaggerClient
http_client = RequestsClient()
http_client.set_api_key(
'https://api.optimizely.com/v2', 'Bearer <TOKEN>',
param_name='Authorization', param_in='header'
)
headers = {
'Authorization': 'Bearer <TOKEN>',
}
client = SwaggerClient.from_url(
'https://api.optimizely.com/v2/swagger.json',
http_client=http_client,
request_headers=headers
)
My question is, how do I properly add authorization headers to a bravado SwaggerClient?
For reference, a possible solution is to add the _request_options with each request:
from bravado.client import SwaggerClient
headers = {
'Authorization': 'Bearer <YOUR_TOKEN>'
}
requestOptions = {
# === bravado config ===
'headers': headers,
}
client = SwaggerClient.from_url("<SWAGGER_JSON_URL>")
result = client.<ENTITY>.<ACTION>(_request_options=requestOptions).response().result
print(result)
However, a better solution, which I still am unable to get to work, is to have it automatically authenticate with each request.
Try again, fixing the host of the set_api_key line.
from bravado.requests_client import RequestsClient
from bravado.client import SwaggerClient
http_client = RequestsClient()
http_client.set_api_key(
'api.optimizely.com', 'Bearer <TOKEN>',
param_name='api_key', param_in='header'
)
client = SwaggerClient.from_url(
'https://api.optimizely.com/v2/swagger.json',
http_client=http_client,
)
Here you will find documentation about the method : https://github.com/Yelp/bravado/blob/master/README.rst#example-with-header-authentication

Using JSON data from API GET to POST to another API via python script

So, I'm new to python and am struggling, self taught, and still learning to code. So be easy on me :)
I am using a script to get data from one source (Jira's API) and trying to use those results to post to another (PowerBi).
I've managed to successfully get the data, I just don't know how to pass the data to this other API.
I know how to use the GET and POST calls, it's just using the data from one to another than I can't seem to find anything about. Assuming since what I'm asking for is very specific?
edit: I also want to mention that while my get is asking for specific data, I'm getting more than I actually need. So I need a way to specify (hopefully) what data is actually being sent to PowerBi's API
import json
import requests
url = 'https://mydomain.atlassian.net/rest/api/2/search'
headers = { 'Content-Type' : 'application/json',
'Authorization' : 'Basic 123456789' }
params = {
'jql' : 'project IN (, PY, CH, NW, RP, DP, KR, DA, RE, SS, CR, CD, AB) AND issueType=incident AND statusCategory!=Done',
'startAt': 0,
'maxResults' : 50,
}
requestget = requests.get(url, headers=headers, params=params)
if requestget.status_code == 200:
print(json.dumps(json.loads(requestget.text), sort_keys=True, indent=4, separators=(",", ": ")))
else:
print("None")
Apologies if I miss understood what you were asking help on, but you could use this to send a POST request as json.
request = urllib.request.Request()#Put the powerbi api here
request.add_header('Content-Type', 'application/json; charset=utf-8')
jsondata = #your json data
jsonBytes = jsondata.encode('utf-8')
#Has to be bytes
request.add_header('Content-Length', len(jsonBytes))
response = urllib.request.urlopen(request, jsonBytes)
You could go with a requests.post instead.
jsondata = #put json data here
headers = {'content-type': 'application/json'}
response = requests.post(url, data=json.dumps(jsondata), headers=headers)
Requests documentation

Categories