PowerShell and APIs 102: How to use Swagger and Invoke-RestMethod with Stephen Valdinger

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone and welcome to another meeting of the Research Triangle Powershell User Group my name is Mike kanakis my co-host this evening Mr Phil Bossman hello Phil how are you good evening come doing well I'm absolutely excited yes hey Phil well tonight we're going to be talking about what what's our topic tonight we'll be talking about uh apis you know application programming interfaces and uh we have uh Stevie coaster also known as Stephen valdi here is uh he's going to give us a quick little intro on working with apis and uh he's gonna you know share some knowledge how you doing Stevie pretty good you're good yeah glad to be back yeah Stevie thank you for joining us tonight um so ladies and gentlemen just to give you a little intro here Stevie is going to be doing an intro on apis tonight and in about 45 to 60 days we're gonna have him back and he's going to do a deeper dive on apis so this is like a part one and part two and so if you're watching this at home make sure you check out the part two version of this if you are watching it at home you can always join us in person uh you can check out our group and find us at rtpsag.com we'll go to Meetup and then you can join us and be part of the live demos but uh with that I would like to hand it over to Mr Stevie valdinga tonight and let him take it away 16. alrighty guys well again thanks for having me back it's always a good time uh to present to this group very thankful that yeah you're going to let me set up some disappointment for the next uh 60 minutes or so no as I said uh kind of coming into this last minute so I kind of cobbled this together so I'm flying by the seat of my pants a little bit um but yeah who am I uh as I've said I'm Steve baldinger AKA Stevie coaster across all the socials Twitter Discord GitHub et cetera Etc uh you can find me there uh support manager at chocolate software is what I do in my day job so I do a lot of package management Powershell some API stuff um a lot of automation related activities go on in my day-to-day so it's always always a good time always excited to wake up and go to work and uh really looking forward to diving into this with you guys so without further Ado I hate slides so we're done with them um as mentioned apis what are they they are application programming interfaces what does that actually mean it's a wave for one system to talk to another say you've got one system that's written in c-sharp that has the need to receive data from another system that might be in Python well those two systems are written in two different languages right C sharp Python and then there's this thing that sits up here that they both need to talk to what is that universal language that both c-sharp and python can speak that's an API that's an application programming interface that means that C sharp can perform requests against that API the same way that python can even though the language that you write the requests and and the code in is different it looks very very different when you go between the two the data that you get back is the same now it might be different types coming back in terms of what c-sharp's data structure will look like coming back to you as opposed to python or in this case we're going to be talking about Powershell and getting Powershell objects back but at the end of the day when you send a request in whatever language to the API the API is programmed in such a way that it has a very structured data tree behind it that allows that stuff to come back you you always get the same properties Etc um coming back from that API Powershell really makes working with apis easy um we'll dive into that a little bit later um the first thing I want to do is kind of talk about how to approach working with an API because there's a bunch of different interfaces out there there's a bunch of different ways to document these things and if you've known me for any length of time you'll know that I will preach to the choir and To My Grave that documentation is user experience and if your documentation sucks people are going to use your stuff so thankfully there's a whole lot of really good tooling out there today to make writing your documentation for your apis very very nice and approachable the first example of that we're going to look at is called Swagger uh yeah so before you get too far there I had a question about what you were just talking about just a clarification so the data that's coming back from an API is sort of a standard raw data format correct and then whatever you're meeting that with in this case Powershell is going to transform that into the tool that you're using to read that API right so if it's python it's python data if it's Powershell it's Powershell that comes back but the data that comes back from the API is sort of uh it's basic it's not it's not configured to the program right the program does the conversion when it gets the data correct exactly uh and typically in 90 of use cases that that data is going to come back to the come back to you as Json and then it's up to the programming language to interpret that as something and it might come back to you as plain text it might come back to you as as X and L it just depends on the API however its schema is defined in terms of how the data is going to come back to you 95 or higher percent amount of the time that's going to be Json um but it could be something else and hopefully the API is documented in such a way that it tells you what to expect from that endpoint okay and so the benefit there so the benefit there is when stuff comes back and you're using Powershell Powershell does quite a bit of work behind the scenes to make that into an object that we're used to with Powershell when you're using another language it may not be that convenient you may have to do some work correct yeah yeah and and c-sharp for example you'll probably have to receive that Json and then serialize it into some sort of way maybe you've got a class that has certain properties on it and you take that serialized Json to populate the different properties on that class say if you had an API endpoint for example um called car and that API when you did a get request sent you back the make the model the caller number of doors it had how big the motor was Etc et cetera you could have a class in C sharp that says hey this is class my car and it has these properties it's make model collar door number whatever you would receive that Json and then set those properties based on the response of the Json and then do something with it Powershell is super awesome in that if you do an invoke rest method against an API it automatically takes that Json and turns it in to a Powershell object for you so you get all these properties back etc etc um and one request jump in yeah sure I was just going to say one of the big advantages of working with apis is different languages have different strengths and different focuses so in C sharp where you're saying you know I want something that's very strongly typed and memory safe you may be best served by keeping it in C sharp because you know exactly what everything is going to look like basically 100 of the time unless you're really throwing out a different pattern but in Powershell you're saying hey I just need flexibility take the data that comes in and parse it to something that I can be over and using and that's really nice that you know a web server may have a very different Focus to here's how the data is going to be used versus a Powershell client trying to just say hey get me the idiot and let me have some properties to work with yeah absolutely absolutely um and there's nothing stopping you inside a Powershell too of doing some work to capture that response from invoke rest method and then taking that data creating your own PS custom object that's got strongly typed data inside of it um and just returning that maybe you let the web server send you everything and then you send back to the user a PS custom object that's only got three or four things on it whereas the web server sent you 12 Etc um so it is very very flexible inside a Powershell as well but yes you are correct C sharp is very very type type safe and you kind of need to use the language that makes the most sense to you this is a Powershell group we're going to do it all in Powershell but if you've got other developers on your team that or other areas of your business that use other programming languages they can still leverage this stuff because an API is universal but not to digress too much um a little bigger because yeah before I started I was going to say if you could bump that up just a little bit and then some of the guys were asking when it fits appropriately if you can just maybe talk about invoke rest method versus invoke web request but that could be anytime yeah sure yeah we'll dive into that stuff a little bit a little bit later because I'd like to show the difference rather than while I'm talking through it um so this is a Swagger dock so if you look we've got this link here that says swagger.json you can see this um in its raw Json format but Swagger is so this is the schema for this particular API and this is a sonotype Nexus repository server um this is the schema for that API when you do a certain request say to this endpoint you make a get request it's going to give you back um this kind of a response and then these things here it's really hard to read it in this format and so they thought let's make this prettier this is what Swagger gives you and then the really cool thing about Swagger the thing I like about it a lot is I could come in here and let's pick this V1 blob stores endpoint I can look at it and see that oh this doesn't take any parameters it's going to give me a 200 response back if the request was okay and this is the type of data that it's going to send me back so that I know for my programming perspective when I go to wire this up and write a Powershell commandlet or whatever to to interact with this this is the data that I'm going to get back and if I want to look at this in a little bit more detail I can click on model and expand this out and it gets a little hairy trying to expand this out a little bit but you can then more clearly see that name is a string type is a string unavailable is a Boolean we have some integers in here etc etc so Swagger really cleanly defines well the Json clearly defines the schema through the API but Swagger gives you a really nice UI on top of it to expose it and the nice thing with Swagger is you get these little try it out buttons so if I were to try this out for example you'll get this execute button and when I execute this it's going to give me an example which is a curl request um it always seems to be curl it's very very rare that you get a Powershell Centric um big sample here but it gives me the the curl command that I would need to do the same exact thing it gives me the exact request URL that I sent it to and then it gives me the actual response from the API so in this case I only have one blob store on the server um and these are the properties of that blob store returned from the Json so when you're thinking about interacting with an API powershells are really really really good candidate for wrapping this API because all the data you really need to make a really good commandlet for this is in here um so if we were to break this down for just a second we've got a method which there can be many methods for interacting with an API a get request do you send a request to an API and it sends you data back it says hey give me the information from this endpoint perhaps with these parameters sometimes with no parameters at all and it sends you back a response with that data as defined in the schema a post request is where you say hey here's an endpoint where I can create something or I can add something to this system via this API via this interface so it allows you to craft a body which is in Powershell will be nothing more than a hash table with these properties so if I wanted to for example create a new file blob store I could say hey I want to do a post request to this endpoint with a content type of application.json or application slash Json and my body needs to have these these properties inside of it and if I get everything right and I send that request I will get a new file blob sort created for example and there's other methods in here too we've got some puts which is hey here's here's some data I want to update a record it's going to update that record now and a put will say here's all of the stuff for this schema if I don't fill all of this stuff out the put will allow nulls into some of those fields which may not be what you want there's no there's no patch types in this particular API um but there's a very there's a very important difference between a put and a patch a patch will update only this stuff in the body that you gave it so say you've got a a schema that's name ID and telephone number for example and you do a put request with name of Bob and an ID of three and a telephone number of some seven digit telephone number the put requests will update all of those things now you do the same put request again to update Bob by changing his name from Bob to Bill and then that's all you put in there you say hey send this Bill request in there it's not going to work it's you're going to get a new record with Bill with nulls for everything else or an error depending on the API spec rap but rather if you did a patch and you sent a request it would only update the field that you had in the body um very very important difference some and you have to watch out for the apis too because puts and patches can be implemented to where a put does a patch or a patch does a put or they're just raw um hopefully the the people that wrote the API kind of know what they're doing and have done the right thing in terms of this is a put request so you expect a certain thing to happen in a patch request you expect a certain thing to happen and they've got it right um but if nine times out of ten not not very many people deal with with patches you'll see puts an awful lot more and then of course you have your deletes which does exactly what it says on the 10 if you send a request to this endpoint it will delete whatever is in the body um a good one to give you an example of that do we have a blobs throwing yeah so if you send me um a blob store and you put the name in the URL so this is another type of request and we can dive into this a little bit too um if we hit try it out here and I just put like default in here and hit execute bad things that would happen I don't want to do that um but let's do like Bob for example and say execute so we can at least see the request so had this worked you can see where the name kind of ends up in the URL you don't necessarily have to have a body for a request you can do an API that has query strings in it as well which is when you see that like Ampersand and then question marks around stuff that's that's query string parameters that's another way that you can um interact with apis it's Hit or Miss whether an API does it that way or not um if it's going to be a Swagger dock like like this chances are it's going to be about any request and not a a query string but it is important to know that some apis are are that way that you can do it all all within the URL and not have to worry about a body at all um what else is inside of here that might be interesting I think that covers everything that I wanted to look at in terms of a Swagger dock just to show you a couple of other things and show you how vastly different API stuff can be this is a Swagger dock API reference this is the API reference for Twitter as you can see it's not really as neat it's neat but it's it's different uh than Swagger so if you wanted to you could like get all your like tweets or whatever um and if you go in here you can see here's the endpoint URL here's all the authentication methods here's the the path parameters etc etc here's the query parameters and then here's some example code stuff in different languages um is not as easy to read this and understand what's going on as it is in a Swagger dock um you can kind of write your documentation however you want to so it's it's kind of up to up to you what you use uh I prefer Swagger for everything um but yeah you'll you'll as you get started playing with apis and trying to figure out how to wrap things be prepared for a little bit of confusion and a lot of red text and a lot of staring at the screen wondering what the hell's going on uh as you're trying to figure things out um these these actually have a couple of helpful links inside of here though and I don't think I don't think I have a postman install on my Mac I don't um but Postman is a great tool for playing around with apis before you start um tinkering with a power shell so what you can do in here is basically tell it what what request type you want what the URS URL is going to be and then start filling out all the different parameters whether that's if you use params like it shows here and let me see if I can't zoom this image in or click on this image can I see this a little bigger yeah Stevie I was also going to mention um as you were talking here that apis can vary in complexity of it I can and so when you're starting it's a lot easier to start with a really simple API maybe one that doesn't even require like any actual authentication and just oh yes getting and putting 100 you know and posting and and before you move to the Twitter API that has probably a very specific way of dealing and getting back lots of different types of information yes absolutely 100 um but Postman is a great Tool uh it is it's pretty easy to at least poke things in this before you go writing any Powershell code um it's pretty fun so the param section you can do like that query string nonsense that I was talking about uh the body can do the body stuff that I was talking about um any assets people are saying in the chat uh you can choco install Postman uh and it will it will give you that application uh it's available out there on the community repository so it's really quick to install it and keep it upgraded you can also do this kind of stuff with um the web browser as well so just to show you that let me do a get request on this one and I can do an F12 here and just to show you what this looks like if I do an f x kit on this we can see this request come through and if we look at the headers you can see here are my request headers and then here's my preview of other response basically and if we look at the response here's what it came back as and if you really want to cheat and get started quickly I don't recommend this but to get started it it does work um if you come in here and right click on this request and say copy you can say copy as Powershell and then you can open up a vs code and do a little paste inside of here and it will give you everything you need now this does it in a weird way that I don't particularly like uh what it uses in book web requests instead of uh invoke rust method um but two it gives you like all these weird cooking things and things as well um which in and of itself isn't bad but um it's just a little messy especially for a newcomer um particularly when really all you needed to do uh to make this request barring that you are authenticated uh would be uh invoke rest method against this URL here and this is going to fail inspect acular fashion um but I want to type location trace on and let's do a method of a get which is default behavior for invoke uh rust method if you just do invoke rust method URI it's going to assume you may get and try that um anything else you definitely want to specify the method but by default it's a get um but you can see the invoke rest method way of doing things is quite a bit simpler than all this nonsense that Chrome devtools gave you but if you are just getting started and want to really do something quickly it's there it's been there for a while now uh I don't know how known that feature of devtools is in Chrome but it's it's there it's been there for a while and it does what it says on the tin it works um yeah let's uh let's look at one more API example before we start having a little bit more fun um so we've got the clouds layer API as well just to give you yet another example of what API documentation could look like this one's a little bit easier to read in my opinion than the Twitter one but still not as good as a regular Swagger dock is um it gives you uh the required parameters so for this one you need an API key you need an email or you need a user service key um depending on what what authentication method you're going to use with a specific header so you can either send an x-off key header with your API key or an auth email with an email address or a service key and it might need to have one the other both all three it kind of depends on the API what the authentication looks like now I am going to show you a really cool module out there that takes say we want to take this and turn it into Powershell um there is a module out there uh from the Posh woof called Corona PS which will take that curl string that we just copied so if we were to come in here and say uh CS equals and then let's do a here string and paste this in and close this off we can then do uh uh convert to oops convert to irm and then my Cs and we get a hash table back with um everything we need to Splat that to uh Iran so if we were to do like uh Splat equals that and then do irm at splat it's going to fail because obviously that's not right data in that example request but that would work and it would allow you to really quickly say hey here's a curl example from this documentation I want to really quickly use this with rust method well you can do that uh with that with that module um It's relatively accurate you might have some cases where the curl doesn't quite 100 convert correctly into the Splat um but it's it's pretty good and it does speed you up quite a bit so just so you guys are aware aware curl the PS is out there it's available you can install it from the gallery uh install module if profecta reminds me Stevie I can remind you whenever you hit a web page just zoom it up one or two on each page what does it not keep it remembered damn it I forget every single time um but yeah Corona PS it's it's pretty handy um and let's let's have some fun now let's uh let's put some of this into practice now I've already done a ton of work with this API because I've already got a Powershell module called Nexus shell which wraps almost 100 of this API as Powershell modules but we'll kind of break it down a little bit and show you what it looks like to actually uh attempt something like this yourself so we are definitely going to need some authentication for this so let me kind of minimize a bunch of these so that I can find the authentication piece in here oops that no no no no access repository management this is an absolutely huge API there's a ton of stuff in here geography is yeah look at all the stuff there's so much stuff that you can do in here now if I remember correctly which one of these actually I think it's just a a letter that you need now let me make sure half pregnancy authentication method all right I'm gonna go cheap and we'll Zoom this in just a little bit ah why what'd it do where did it go we still see it yeah what the heck is going on why why did you do that I don't understand why I did that what is it doing Weird Al's all right fine that works um so if we go to source and we go to public and we scroll down we get this um let me see if I remember how to do this yeah they say a man who presents live has a fool for a presenter yes yes that's that that's me I'm this guy uh we do that and then we send the result and we get that back being beautiful okay yeah so all all the authentication is on this one is a header um I was thinking of a a different one uh if we go to Dallas stop chocolatey just to show you an example of what it would look like um differently usage API examples um we'd first need to um authenticate to the API and that's where we did this here um if you notice we write a session variable here and then this session variable is passed to everything else um if you do a session variable that that saves a cookie basically um and then in inside of that session variable there's a cookie that is your authentic authentication uh cookie and then you can use a web session to pass that back and forth so that's how our Central management does it is via that cookie um the Nexus API is just a header and I had to remind myself of that because it's been been a minute so if we look at this um I'm just gonna real quickly steal this code so I can walk through it over here let's just put this in put this in here and let's Zoom this in a little bit closer and I'm going to write this down so what are we doing um this creates an authentication header uh that you will use for all your other calls to this API once you have that header crafted you can just add past that header to other invoke web request calls and it'll be right in this example uh we take the name of the server so in this case it would be chocolate server.stvcoaster.dev we give it the credentials of the user that you want to authenticate to the API in this case we'll use the admin account on server because that's the only one that exists because it's a demo box the path which could potentially be different depending on the server you hit because in this particular case Nexus has the concept of a context path so this could be something like eight four four three slash Nexus to get to the root of the server instead of just hanging off of the port here for example so we take into account that you might have a contacts bath and we provide you with parameters to tell me whether or not this is an SSL backed instance of Nexus and what the SSL Port is by default by default Nexus will use port 8443 when you're using SSL but if that's the only web server running on the box you might want to make that run on 443 so you change it um but the default is eight four four three so it set its default here and then based on those parameters um if we use if we say this uses SSL we set that protocol variable uh in the script scope so this is available across the entire module to https and then we set the port to whatever you specify the SSL port to be so that we get whatever is after the colon correct otherwise we set the protocol to http and the port to 81 because that's the defaults for um uh a regular non-sl instance of of Nexus and typically that doesn't change when I've never seen a Nexus instance run on Port 80 for example say always run on 8081 that could probably be improved but whatever um and then we set the hostname variable to a script scope again just so that we can reuse it other places across the module and then we set our contacts path to whatever that path variable was and then very importantly we get into different types of authorization uh inside of headers in this case we're going to use basic authorization which is just hey the word basic and then a space and then a base64 encoded username and password pair so it's username colon password a64 encoded now I did it this way for compatibility reasons if you're just straight up using uh Powershell seven or Powershell six and newer I think um it does have the authentication and um token stuff baked into it so you can do like invoke rest method and then authentication there's basic and bear I believe yeah and then for those things if you use authentication uh basic and then a credential with a get credential object for example it will do this bit for you you don't have to you don't have to worry about this stuff it's all automatic so um if you're going to do anything with apis pretend that Windows Powershell is dead just use Powershell seven it's so much better in Powershell 7 when you're working with apis uh the way the the data is formatted and Returns To You by The commandlet is amazing there's all this additional authentication stuff baked into it there's a ton of extra stuff on invoke rest method now and actually if we do get help cool rust method online let's just go to the docs like there's a lot a lot of parameters that you can give to invoke rest method now uh in Powershell 7.3 as opposed to um Powershell 5.1 so you can see it's a way way less robust in Windows Powershell than it is in Powershell seven it's absolutely a dream to work with it in Powershell setting um paging is nicer inside of it uh form stuff is nicer inside of it it it's just better if you're going to do APS stuff forget that windows power show even exist just use Powershell seven uh and then what else so we build that header and they don't actually need wait we do keep that credential hanging around um for a very special reason in this particular module um pretend that doesn't exist though and then we make a request to an endpoint I I've picked the status endpoint here to just use that header just to make sure that it worked so we can say uh error action stop and then if that request works we get connected to the host name and then if it didn't work it it throws uh an exception message so if we were to take a look at this and we were to run connect access server and we were to say hosting me hopefully you guys can see that terminal okay and there I want to use SSL and I want a credential oops yeah see didn't work so now if I say admin maybe Control Plus that just go a little bit yep how's that a little better yeah so as you can see I type my password wrong the first time and I got a 401 unauthorized um and then the second time I got connected so I've now successfully got my header uh stored as a script scoped variable I'm outside of outside of my module right now so it's going to be a little bit different but let's go back to where there is let's go back to this and let's go interact with hit API and I'm probably gonna have to go all right server don't be dumb that's a bit why are you being dumb is this you no is this you yeah you're fine why are you being dumb over here alrighty then let's go let's go back to this API let's see what can I grab um let's do a repository so repositories let's find a nuget hosted one let's do this one so what does this look like we're going to write a commandlet that will leverage this API to list all or give me back an object of all of the uh nuget hosted repositories on this um server so if I were to do chocolate internal and I hit execute and I look at this request and this is the request URL and it did use just a URL there's no body to this and then it gives me an object that looks like that so what I like to do when I do design apis is I take this and I'm going to say um function and let's give this a name I know it's a get request so I'm going to call it get and I know it's against a sonotype Nexus API or a Nexus server so I'm going to say Nexus and then what am I actually getting I'm getting a nougat hosted repo for example and then if we look at the API we have a parameter that is a string called repository name and it's required so in my function I want to do uh commandlet binding and let's build a parameter and let's call it definitely want it to be mandatory we want it to be a string and we want to call it repository name so that it matches not just a parameter here now it doesn't have to really match 100 like if you wanted to just call it repository you could um but I like to be as close to what the actual parameter is in the schema of the Json as possible so that when I'm looking at the code here and looking at the schema they match kind of one to one and then what do we need um that's all the parameters for this API so what we need is a process block and then we need a URL so if we look we're going to cheat a little bit and just grab this URL here because I know that's what it is it's a little bit different in Nexus show how I've done things but that's more for part two because I'm doing some weird things over there so I'm just going to define a URI variable equals and we're going to put this in here do that and what I'm going to do is take this variable and put it right here so that because this is in double quotes that variable will expand out and that you are will be correct based on that if I were to do this in single quotes that variable would not expand and you would try to get a repository literally named dollar repository name and you would have a bad time and you would pull your hair out because you're like why is it happening what am I doing wrong and then you realize he's the wrong quotes and then you kick yourself for a while and then you move on at least that's how it works with me so what do we need next we need we need to call invoke rest method we know that but what do we need to call it with so what I like to do to keep my lines really short because your brain Scrolls this way a lot better than it Scrolls this way so keep your line short if you can um and what that might do here like you might even make this a little bit short shorter yet and break this apart but I also realized that I'm zoomed in a little bit farther than I normally would be so this is fine uh so what I'm going to do is call this irm params and this will be a hash table that I can use to splat it and what do I know I need to pass to invoke arrest method for this to work well I know I'm going to need a URI now we've defined that above and I know I'm going to need a method which I know it defaults to get but be explicit because it'll bite you in the rear end if you don't um I know I need headers and because of the way I've crafted this connect their script level so they are available so I can say headers and let's add to this and then we also need to tell it the content type of application Json so that invoke Russ method knows what kind of beta is expected from the response so it can do the right thing to format it and give it back to us and then we need to splat it so invoke rest method at irm params that's a whole lot better splatted and readable I've been doing invoke best method URI method get prompt to type blah blah you kind of get the point splatting is amazing now let's just see what this function does shall we so let's do uh get Nexus nuget hosted repo repository name chocolatey test and see what it gives me uh 403 for a bit well you know what this yeah that's gonna Leach this isn't going to work outside of this so I'm going to make this a little better get her janitori uh potential oops we can tell you've typed that before a few times yeah it's been a few times and then let's just steal this and this and this and put this here and clean this up ever so slightly go through this let's do oh you know what I called it headers and not header so let me do yes it's going to ask me for a credential that's fine there we go that works uh there's a question is it okay to use PS credential instead of typing all that out absolutely um that one will probably be fine I just know that I've been bitten in the ass before by assuming that.net will find the write type for me where the ending type might be the same in two or three different classes and the only way to get the right one is to fully qualify it and best practice is the fully quiet fully qualify this stuff anyways in terms of the these kind of things um just so you don't run into any surprises um but yes doing it as just PS credential will work um I've just been bitten and they asked enough times to know that fully qualified please um so this works and this gives me everything I would expect so if we look at this and we do the same exact thing again actually let me do uh let me do this uh cred equals get natural I'm going to grab my stool thick or tired standing all day there we go that's a little bit more comfortable and then we do cred that looks good then we can do oh this and we can pass a credential like that and let's do result equals that so now if we do result we can do get member on it and if we look at this it is in fact a PS custom object so yay you didn't have to do anything magic to to get that object back you just got a one-to-one whatever was defined in the schema of the API as something that would be returned is what you'll get back um via the API so um in this result object if I wanted to I could just the new DOT name and get name I could do um dot storage and give me all the information about the storage so for this we've got a blob surname of default uh content type validation of true and write policy of allow et cetera Etc it's all there I didn't have to do any extra work it just magically happened for me it's great um but let's say that perhaps result had too much data inside of there I don't really care or I want to do something different for example um we could go out and go off into the weeds and change this a bit so we could say result in our function looks like this and then we could say uh PS custom objects and and we could say blobs or name for example is equal to result dot name and let's say we know that the format is nuget because the commandlet was get Nexus nuget hosted repository so I don't care about that one I don't care about the URL either I do care about whether it was online or not so I'm going to say online equals result Dot online and I care about uh cleanup policy stuff so cleaner policy equals result dot uh cleanup and that's all I want because um I know the type is hosted so if I were to F5 this come up here and rerun this again and do result I get just just the data back I cared about I manipulated it inside of the function to control exactly what it looked like to the end user um so just because the API schema dictates that this endpoint is going to give me back this information doesn't mean that's gospel when you're wrapping an API and giving it back to the end User it's it's just going to to me that you you have flexibility there right if if you want to change things around um you can yes this is a PS custom object you could do other stuff here too um decade Implement classes so that this thing is like a very specific type even maybe you want maybe you want this to be returned such that you could do something like a um nougat hosted repo type like that gets really into the weeds of using classes of Powershell and then wrapping apis that's that's for down the road come to Summit um but you can do all kinds of cool stuff with apis um inside of Powershell I'm going to stop there because I've been talking for a while and not paying attention to the chat and it's been quiet so if there's any questions that haven't been answered in the chat I know we got some pretty smart API folks um I think we've been keeping up with this so okay cool yeah I think we've been keeping up with it some people have some questions but I think Clem has been doing a fine job of helping people out excellent excellent Stevie in your in this particular example up above you have results equals and then irm and it doesn't you're not using that particular variable anywhere else higher up well we're at the previous function there it is yeah yeah so this I use the result out of habit I could have used it in all here because this API endpoint that I'm using to send a a header just just so I craft a header and build it like technically I don't even have to do this um technically all I would have to do to make this work is something like uh this so if I go to just like Steve coaster I just did this the other day um make this big um really this is all I need really all I need to do so um what this function does is rather well I can show you what this function does so I don't know if I take this and I copy this and I put it over here and then and I do get or new encoded credential credential cred it's going to give me that base64 encoded credential back to the the terminal but if I say as header it's going to give me that header back so if I were to do something like this for example I could then do invoke rest method um some URL something header headers header and it would work um I don't necessarily have to call an endpoint here um all I really need to do is build a header but the reason I call an endpoint here is to validate that I gave it the correct credentials because if you saw when I first used this connect function I got a 401 unauthorized back that's because I typed my password wrong I didn't want to create a header with the wrong password and not know it after I use the connect function and everything looked good and then I moved on and I used another function and then all of a sudden it blow up in my face with the 401 unauthorized I'm calling this particular endpoint here because it gives some sort of a simple Json response back that I don't care about so I just null it I don't care I just care that the invoke press message worked so that I can wrap that in a try catch with error action stop so if it worked great if not throw a message in this case for one uh unauthorized but that's why I used to result I'm just used to typing result equals because I'm burying the response I don't want to see whatever the output of this was and yes it's a Powershell seven which right host doesn't kill puppies in so it's perfectly fine how she looks Studio looks like we got two people that want to ask questions so Jason go for it what you got um yeah I'm kind of curious uh I guess if you have like a best practice for this scenario um if you're building a module uh you know writing several commandlets within that module to interact with an API you know a lot of times you look at situations like well like Azure you know connect Dash whatever right um log in dash whatever uh you know they're they're logging in once getting that that token uh that Bearer token and they're stuffing it somewhere um and then and then after that subsequently you're not having to stick a credential on every single Command right correct um do you have a best practice for sharing that credential between your different commandlets in that module uh in this particular look at the easiest thing to do is script scope because that locks it into that module so if you were to say next to cell Nexus shell is a really good example it uses a script scoped header variable that's that is available to all the functions in that module but if I were to use invoke rest method outside of that module and try to pass header to it it wouldn't know what the hell I was talking about that doesn't exist so it lives inside of the scope of that module can you get to it with Powershell yes you can um what's the likelihood of somebody knowing how to do that uh it depends on your team uh if your team is full of really really smart Powershell people using a script scope variable is probably something that you could do better um but it's it's pretty safe so that's one way to do it um another way to do it is to rely on secret management module and just have your authentication pull from a vault like Azure key Vault for example or whatever um again you're going to have to authenticate to that stuff somehow but secret management is a really good uh good way to retrieve that stuff and then pass that along as another module author I'll throw out my opinion that using the script scope is typically a great way to go works very well if it's something that doesn't need to be just a single instance then yeah using Secrets management is fantastic if you do have an instance where you need to have only one credential or one object in the entire system for whatever reason then using something like a name to mutex is a fantastic way to go as well yeah what was that a named mutex it's a it's a pattern that allows there to only be one object existing and accessible at a time on your system nice thanks absolutely I think we also have a question from Ben and so Jason uh make sure you take down your hand when you're done nice okay just Ben what what can we help you with hello so I actually ran into this today working on one of my modules that wraps the API and I want to get your thoughts on the solution um so I had a need to determine if uh the results from invopress Method All actually returned anything so so in your example the dollar sign result is there actually something in there um and the only way that I could figure out how to do that reliably was using and this seems wrong which is why I'm asking is using the string is null or empty method on result and that returns either true or false if invoke breast method returns something or doesn't if I did a a result the measure object dot count or result.count those all returned one even no results were returned and so I was wondering what your thoughts on that were uh typically what I do is I just do something like this and let Powershell handle it for me if a result else something else um because if this didn't give me anything back this is going to be empty and this is going to be false so it's quick and dirty it doesn't work a hundred percent of the time um checking if this is null is really good so um if not all naughty cool result uh for example um yeah that that I tried that too and that didn't work for me like yeah because yeah technically not null so yeah exactly yeah it depends on the end point it depends on the end point too like there are cases where invoke rest method no matter what it's going to have something returned from the API I've seen that a time or two uh where that something is junk it's completely worthless but in bulk rest method got something so there's something in there that seems to be what I'm getting in my case so yeah what's the API thing just out of curiosity is it like something internal or it's it's it's something internal and actually something that I wrote too so um yeah it's uh yeah it's it's written on uh I wrote it using the larval PHP framework oh okay okay but yeah apparently uh even though I'm returning no results Largo still for some reason are returning something rainbow breast bad let's see it's something um because yeah the result is not nully we went no results are returning from the API yeah yeah it definitely sounds like it might be might be a slight of active side effect of laravel yeah yeah that's that's my guess as well but yeah cool thank you appreciate it absolutely anything else I don't see any other hands up so feel free to go how you please all right I'm just gonna sink in through it all the best practices or uh you know short-lived tokens and stuff ah I don't do a whole lot of stuff with apis where I have to worry about that so I don't have a ton of experience with handling short-lived tokens um what you could do is so for example we've we've used this connect Nexus server function to create this header and return that back and then it's used other places like here for for example um what you could potentially do um is do a a try catch here so do a try uh if it fails and the error messages of 401 unauthorized for example just run your connect again gotcha you can do it inside of here so you can say um and it it's it might not be exactly that you what it you would need to send your connect again whatever that is um whatever that's going to look like just to refresh that token um and there are ways let me see it does um do like a right eye but your credentials have expired and you're catch block yeah connect and then I continue something like that both of the like really good apis have some way to like reading off the token oh yeah I mean some yeah yeah renew your Bearer you can have like a refresh token um yeah exactly there you know yeah it's again it's up to the API how they Implement their authentication how it how it's handled um yeah what I've done in a module that I worked on can you guys to hear me okay yep yep yeah but what I've done in Amazon I recently worked on was I created a single object that acted as like the I I don't know if this is the right term but a state machine for it so once you did your connect command it created that object um and then what built within the connect command I had a variable of with the token there lifetime would be the chicken getting from the docks um you know and I always added like a pad to it you know like minus a minute or minus five minutes or or whatever so that you know it technically never really runs out um and then um within my module I had one generic command so each sub command like say get some some record um would just set the splatting parameters for then a single do the Dirty Work command and then the duty Dirty Work command uh checks the the global object looks for the you know to see hey see Bears still alive or did it expire if not it just reruns the connect command and if not then it just does the you know the needful if you will so um that that's kind of how I did and it actually worked really well nice one of the things I'll throw out um I put it in the chat but um and Bill Rex method has this follow Rel link parameter to it so if you have an API that returns data in chunks pages of uh the records for example um and has uh uh you know Returns the proper kinds of headers that tells you how to get the metal chunk yeah um the follow relings will do that for you so you don't have to write code to to get the next page and it returns everything all at once and so um you know if if if you're timing out because you're manually paging through the data that may be a way to avoid a timeout yes and I believe I can check the docs let me look um that's it must be pretty new yeah yeah yeah it is it's not in windows power show I I was almost sure that that was something that uh the core commandlets this is why I say sorry this is why I say that a Powershell core is the only way you should be interacting with abis the the web command lists inside of Powershell seven slash Powershell core or whatever you want to call it Powershell um our light years ahead of of the windows Powershell stuff um and the windows Powershell stuff isn't going to get any of these Advanced features and and new functionality that's in in Powershell today well that's interesting it is not in uh web request it's only in rest method right yes yeah great and they had to do that yep yeah invoke invoke web request is good for like web page stuff but if you're going to do an API using book rest method because it like soap apis are practically dead anymore Everything is Everything is a rest API that's really really super popular there's still some stuff later out but let's let's face it there's there's far more rest stuff so use the commandlet with rest in the name so the quick question on that because I think I when I was running that module I used web requests because um I wanted to make sure like the status code was like what's it like 200 okay or whatever um can you is that available in rest method uh um do I still have result is it still a thing in here but um so there's a so there's a um a parameter called status code variable where you can get the status code is that's what it is you can get the status code back in a variable and check that there's also other ways to get at it um from the result that you get because um and then also isn't isn't it true that if any sort of error code like the 500 or 404 occurs with rest message rest method that it will throw and then you can do that deal with that in a try catch yeah yep yeah that yeah I figured as much but I didn't know how to get the uh to be able to actually parse the error code out of it at least you know I was just trying to do it 100 miles an hour and build something that worked to solve a problem real quick and ended up writing a fully functional module instead isn't that the way of it that's that's the way it always guess yeah um I don't really know how much more I want to talk about I've been talking for a little over an hour now and I'm going to be doing more of this in a couple of weeks like a part two thing we'll dive into this a little bit farther we'll kind of expand on this a little bit we'll we'll flush this out uh and we'll go into the weeds of of really and truly wrapping a module a little bit it's funny you mentioned that because I was watching you and I was like wow this is what he threw together for an intro yeah um and so um maybe maybe share why don't we want to put a nice bow on this so for those of people have been watching at home may not be understanding what we're talking about uh Stevie helped a group out tonight with a last minute change of scheduling and jumped in and extended a demo that he's going to do for us in a month and a half into basically a two-parter and so tonight he put together this demo with about 90 minutes or two hours of prep time and so he did an amazing job and that's why I was saying wow this is what you put in a intro and so as as we mentioned we'll be coming back in about uh six weeks so maybe less and uh middle middle of March he'll be presenting on essentially the part two of this which will be a deeper dive and so um what I really appreciated tonight was a lot of useful examples and lots of great input from the community lots of great questions lots of good examples in the chat unfortunately if you're watching at home you may not see the chat because that doesn't come along with the recording and so that's why I always encourage people to come and join us in person if possible um but Stevie fantastic job and uh I'd like to ask everybody if they could to give Stevie a round of applause for stepping us stepping in for us last minute uh that's a really wonderful thing you did for us tonight and we appreciate that so much no not a problem yeah um and so with that folks we're gonna wrap this one up tonight um as I was just saying this group meets in person on the first and third Wednesday of the month and we'd love to have you come and join us so you can participate in the discussions in person and live uh to do that you can visit us at meetup.com and look for RTP Sugg or you can go to rtpsug.com and get information on how to join us at the next meeting Phil anything you want to wrap up with here before we finish this no just encourage everybody to join us in person and uh well happy to have you thanks for doing this yeah and so Stevie thank you so much and thank all of you to hanging out with us um check out the other videos we have on our Channel we have about 120 videos and well sure you can find some more content until next time we're going to say thank you and good night
Info
Channel: Research Triangle PowerShell Users Group
Views: 1,114
Rating: undefined out of 5
Keywords: PowerShell, API, RTPSUG, Swagger, Invoke-RestMethod, NuGet, HTTP
Id: We794Vx3IQc
Channel Id: undefined
Length: 79min 43sec (4783 seconds)
Published: Thu May 11 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.