Integrating Amazon Lex with ServiceNow

In a recent post, I covered creating chatbots in AWS Lex and created a simple bot for ordering jellybeans.  As promised, I took my bot and integrated it into a custom page in ServiceNow’s Service Portal.  While I’ve worked on several integrations in this space before, this was my first time integrating an AWS service into ServiceNow.

In order to integrate Lex, I needed to provision the following:

  • A ServiceNow instance (Helsinki or later)
  • An AWS Account with a Lex Bot (Created during my previous experiment)
  • An AWS User with the AmazonLexRunBotsOnly policy assigned

With these components in place, it was time to decide on an architecture.  I needed a UI for users to chat with Lex, client-side code to handle the text and transact with Lex, and finally some server-side code to initialize parameters for the service layer that are stored in system properties.

For the UI, I created a new Portal, Page and Widget to host all of the above.   The Javascript SDK for AWS is included via a CDN link.  I would have preferred to keep this piece server side, but the current offerings for the SDK are limited to either client-side or server-side with Node.js, which isn’t available for now.

What was critical to keep server side were the application credentials for the service account itself.  There are several properties that must be gathered from your AWS configuration and added as system properties in the ServiceNow platform.

With all this in place, it was time to test!  First by sending a message to Lex to invoke the Intent for ordering a jelly bean:

Then to follow the same flow of the Intent, telling the bot what flavor I want:

And finally confirm my order:

Depending on how you’ve configured your bot, you can either have Lex return parameters to ServiceNow or to pass them forward to an AWS Lambda or other endpoint.  It’s easy to see the potential here for using Lex to drive another entry point for your Service Catalog or even things like Orchestration.

If you’d like to take a look at the app, I’ve got it on my GitHub here.  I’m interested in any feedback you have as well as anything to share on ServiceNow app development or AWS Lex.  As always, if you have any questions or comments, please feel free to add them here or address them to john@benedettitech.com.

Thanks for looking in!

Chatbots w/Amazon Lex

Recently, I attended a learning event put on by a local developer group: DevICT, which is a community for local developers in Wichita, KS.  The topic was Amazon Lex, a chat platform that you use to build your own chat bots.  Then these bots can respond to either text or voice from users and do useful things based on the outcomes of those interactions.

Setting up Lex is pretty straightforward.  After logging in to your AWS Console, you can navigate to the Lex product and it brings up your list of bots and controls to create new ones.  Once you’ve created a new bot, you’ll need to define Intents and Slots.  To put this in programmer parlance, if you think of your bot as an API framework or class, you could define Intents as methods and Slots as arguments.

For my bot’s first Intent, I took inspiration from a recent trip to the Jelly Belly jelly bean factory in California.  (The tour is free and great for the short people: i.e. kiddos)  So, I created an Intent called ‘IWantAJellyBean’ and seeded some phrases that would prompt the bot to start asking questions to fill in all the Slots.  This is the bridge between plain language and something the API can understand and the platforms language processing can imply the correct intent based on what you say or type.

Next, for my Slot, I created a short list of flavors.  This essentially acts as a type for fulfillment of the Intent.  When the Intent is invoked, a prompt that you configure in the framework adds a prompt to the chat to gather additional information from the customer.

Once all the information is gathered via the chat, the bot prompts one more time to confirm fulfillment of the order.  The confirmation is defined by the developer and you can determine the outcome based on the customer’s response.  Then, you can choose to trigger an event based on what happens as a result of the chat.  You can even leverage an AWS Lambda to take the results of the chat and trigger downstream activity.

Next comes the fun part: Talking to your bot!  This is mostly a debugging step but I was really impressed by how I was able to just use voice to walk through the test.  It’s very easy to see the potential of this platform to automate interactions with individuals and trigger requests or other business logic in your infrastructure.

I want to thank the individuals at DevICT for a fun and interesting learning experience.  If you happen to be in the Wichita area, I would highly suggest stopping by for their events, which can be found on Meetup or Facebook.

I’m interested in your experiences with Lex and AWS in general.  As always, if you have any questions or comments, please feel free to add them here or address them to john@benedettitech.com.

Thanks for looking in!

Knowledge 17 – A Look Back

What is the purpose of a conference?  

To some it’s an opportunity to get out of the daily grind for a few days and see some cool new tools and make some new connections.  Ultimately, it’s an opportunity to ensure that you’re heading in the right direction and to come back armed with knowledge to guide conversations about existing work streams and inspire new ones.

Knowledge is an annual conference put together by ServiceNow intended for any individuals that use or build on the platform.  My involvement this year started with an invitation from a colleague to help with a presentation he was working on for this year’s conference.  After a live rehearsal at our local SNow User Group, I was very excited to attend and both learn from and share with others in the field.

Sunday, May 7th – Monday, May 8th

My conference journey began with a 2-day pre-conference seminar on Business Application Development.  While not highly technical, the course provided valuable information to guide decision making and recommendations for applications on the platform.  Additionally, they provided strategies for identifying and solving pain points or broken windows on the platform in general.

Other guidelines for improving our approaches to development touched on defining measures, such as return on investment or solving common business challenges by hiding or streamlining complexity.  Additionally, we were reminded about how important it is to establish and drive the narrative of solutions built on the platform.  Essentially, to tell our customer base what we’re doing and why and to solicit feedback and adapt our approaches accordingly.

On the development side, we spent some time on effective user story writing as well as best practices around extending the existing core modules and organizing any customizations or new features we implement.   We were introduced to some new features for upcoming releases such as UI/UX functionality and improvements to automated testing and the resurrection of a previously deprecated debugger which will be an extremely useful tool for developers.

For architecture, we went over some basic tasks like table creation and decision making around when to build new and when to extend existing tables.  Also,  we were coached on how important it is to define the scope of a new feature before beginning work.  Applications should have a clear purpose that can be reconciled to the measures of business value and customer feedback covered previously.  You might enjoy building something cool in a new way, but that’s never a guarantee that it’ll see any adoption beyond curiosity or superficial interest.

Tuesday, May 9th

Tuesday marked the official beginning of the conference and the ServiceNow CEO’s Keynote did not disappoint.  A record setting 15,000+ attendees were challenged to improve the customer user experience, protect the value that we’ve created and continually work to reclaim wasted time and resources that can be better utilized elsewhere.  Members of the ServiceNow community were informed of additional efforts to continue to address the gender gap and reminded to challenge preconceptions about career paths for anyone and everyone.

My first class of the day was Angular2 applications for the ServiceNow Platform.  While I’ve been working in Angular for a couple of years now, I had zero experience in Angular2 or deploying a ServiceNow application from a GitHub repo.  This session gave us a walkthrough on staging and testing an Angular app locally using NodeJS, publishing to GitHub and then directly installing the app from a hyperlink on GitHub itself.  This spawned quite a few ideas for myself around better organization of code and sharing that code with others.

Next, I attended a course on Testing Inbound REST APIs.  This is a possible feature for Jakarta that will allow developers to use SNows Automated Testing Framework to simulate HTTP calls against tables and services they build and establish expectations around functionality and behavior on those calls.

My labs were done for the day, so I attended a business oriented breakout called Enabling Enterprise Architecture Decisions Through the ServiceNow Platform.  The session overed ideas and justifications for consolidating existing services and data into the platform to eliminate wasteful and repetitive practices throughout the enterprise.  The idea is that, by removing many of the seams between various layers of stand-alone solutions, ServiceNow simplifies the conversation around enterprise architecture by assembling it into a unified platform.  Additionally, the platform can allow stakeholders to focus on managing and prioritizing services rather than keeping track of nodes and their dependencies separately.

To cap off the day, we had our own presentation on Service Portal. Our topic specifically covered challenges and lessons learned when integrating 3rd party platforms into the Portal itself and providing a seamless and positive user experience.  This was my first time actually presenting at a global conference so it was a bit nerve-wracking.  But, our presentation was well received with excellent Q&A from our audience.  Thanks to all who attended!

Wednesday, May 10th

I started off the day with an interesting session on certifying applications for the ServiceNow Store.  While I haven’t personally built any public applications, the standards SNow establishes for their store can easily inform standards for internal applications as well.  They covered a Top 10 list of common mistakes made when developing, mostly around roles and security.  Additionally, we were reminded of their built in module for certifying applications, which can be useful for spot checking applications or other features in progress or already in the wild.

Next was a breakout entitled Defining your App Development Methodology for ServiceNow.  This was basically an outline of steps to follow when proposing or accepting new work.  Questions around demand and identifying key stakeholders and sponsors and maintaining their interest throughout the process.  Also, there was a reminder that new features always include a subsequent cost of support and maintenance throughout the life of that feature.  One last thing: ‘Have a Testing Zealot!’  Not my term, but I’m using it anyway.

My first lab of the day was on Advanced Service Portal Widget Techniques.  We covered several implementations of a list view in the portal incorporating conventional server-side GlideRecord calls and client-side API calls.  Combined with configuration level constants like table name, we were given a template for a reusable widget that can be easily cloned and tweaked for multiple uses.

Lastly, I attended a session on Analytics and Machine Learning.  This is an equally arcane and fascinating topic for me and it will be interesting how application of AI will inform the ServiceNow platform going forward.  We were introduced to automated Virtual Agents that can act as first responders to customers and learn from previous customer engagements to guide and improve future sessions.  Additionally, machine learning can be applied to data within our existing systems to derive additional meaning from data points that human analysts might miss.

Thursday, May 11th

The last day of the conference definitely finished on a high note with the CreatorCon Keynote.  Developers and other creators were reminded that expectations are constantly changing and growing.  The sheer volume of data and the speed at which the meaning of that data needs to be communicated will only continue to grow.  We should not only be thinking of automation for customers, but also every edge we can gain in our own processes to increase our velocity without compromising effectiveness and overall quality.  Tools such as native automated testing and integrated debugging can only help.

Our last lab and session of the conference was Managing Team Workload and Collaboration with VTB and Connect.  Most of the information on Virtual Task Boards was already familiar territory for me but it was neat to see some new improvements and features, including Connect integration for live collaboration among team members.

Summary

Needless to say, this past week has been a whirlwind of people and concepts and generally drinking from a fire hose of information with maybe a small respite now and then to let those ideas breathe.  What’s most rewarding for me is to see so many people in one place excited and passionate about what they do.  Our work has a soul.  It’s necessary to recognize the value in what we do and continually strive to improve.  Conferences are good for a spot check (sanity check?) on where we’re at and where we’re headed.  I highly recommend them.

I’d love to hear any feedback on this post, especially if you attended Knowledge 17 and would like to discuss your own experiences.  As always, if you have any questions or comments, please feel free to add them here or address them to john@benedettitech.com.

Thanks for looking in!

Azure Follow Up – Closing It Down

It’s been a little while since I wrote about Azure.  Early on, I wasn’t sure how much I’d be focusing on using that outside of my day to day and the truth is, I haven’t touched it much since last year.  Nothing against the service, I just haven’t had a need for dedicated hosting in a while.
 
On that note, I will be shutting down my Azure resources as of today.  I’m in no rush to port what I’ve built so far to AWS, but my projects are on Github for any who are curious.  I may revisit them at a later date.
 
Even though I won’t be actively working in the Azure space for the foreseeable future, I’m still open to discussion and collaboration on the platform.  As always, if you have any questions or comments, please feel free to add them here or address them to john@benedettitech.com.

Thanks for looking in!

ServiceNow Istanbul – What’s New?

If it’s not obvious from my most recent content, I’ve been spending the bulk of my time in ServiceNow.  For those of you who don’t know, ServiceNow is an enterprise application platform that is commonly used for its flagship ITSM/ITIL application.  While IT Service Management is its main use, the platform allows business developers to quickly deploy integrations and services in a cloud and mobile ready state with less effort than building from bare metal.

One of the most recent announcements is for the latest major release, called Istanbul.  This latest version passed into general availability this month and has many exciting new features.  I recently attended a webinar that covered the highlights.  You can find the recorded session here.

Automated Testing – This is the piece that ties back into my most recent series on testing.  The automated testing suite in Istanbul is probably the feature I’m most excited about.  The Automated Testing Feature gives developers a native toolkit for building test suites for both UI and server-side unit testing.  Tests can be organized by feature or combined into multiple testing suites for regression testing for future releases.  I’m a fan!

Debugger ‘2.0’ – One of the challenges on this platform is the debugging implementation.  Often, I find myself avoiding the native debugger in favor of logging by hand or using the browser console to detect issues on the platform.

Istanbul restores a debugger tool that was popular in pre-Geneva releases but was turned off some time ago due to functionality issues.  The updated tool runs in its own window and allows developers to add breakpoints specific to them for working with their code.  This means that developers can simultaneously use the same functions while not stepping on each other’s toes with unwanted test cruft.

HTTP Message Logging – For those of us who work with external integrations involving critical business functions, failed event captures in this space can result in unnecessary impact and reduced confidence in your service delivery strategy.  Adding to this is the possibility of finger-pointing between dev groups and a lot of guesswork in troubleshooting the failure.

Istanbul attempts to help with this by breaking out HTTP message logging out of the box and adding it by default.  This not only helps with visibility and troubleshooting of integration issues in production, but development and testing of new integrations.

Email Unsubscribe – One of the common user complaints that come with new platforms is the volume of email that comes by default.  While the platform already allows users to pick and choose what notifications they want to receive, often there’s a disconnect between the actual notification and the setting users might need to change.

One new feature of Istanbul allows developers to add an Unsubscribe link to notifications they send.  This allows notification recipients to opt out of that traffic with a single click in the moment rather than forcing them to log into their user configuration and then remember which notification they’re stopping.

Email WYSIWYG Editor – User experience is often an afterthought or even forgotten when working with a business application.  Part of improving that experience involves delivering content in a more polished manner, rather than just spamming people with walls of text.

While the previous email template editor allowed for markup content, developers were limited to a code only interface, which involves a lot of guesswork in practice.  Istanbul adds a WSYIWYG editor which will allow for quicker delivery of user friendly web-style content in notifications from ServiceNow.

As always, if you have any questions or comments, please feel free to add them here or address them to john@benedettitech.com.

Thanks for looking in!

UI Unit Testing with Selenium – Part 4 – Selenium Server

 

Last time, I went over more advanced uses of Webdriver as well as putting together a framework of shared methods which can be hooked up to unit tests. For this last post, I’ll be standing up an instance of Selenium Server on Amazon Web Services and refactoring the test framework to point to that instance for testing.

What is Selenium Server?

Selenium Server is basically a hosted service that can accept and run Selenium tests independent of the actual testing client.  This allows for shared infrastructure that can be accessed by various clients without repeating the provisioning and setup of WebDriver files and other libraries.

For the provisioning of Selenium Server, I’ve decided to try out Amazon Web Services Elastic Computing service.  If you’re curious about AWS and want to take it for a spin, you can sign up for a free trial period that’s currently 1 year!  Information on EC2 and a link to sign up for the free trial is available at this link.

Standing up Selenium Server on AWS EC2

So first, I need a host.  After signing up for my free trial, provisioning an EC2 virtual machine using Windows Server only took a few minutes.

Then, I was able to copy over the Selenium Server JAR file and the Chrome WebDriver.exe.  Both of these can be found at the Selenium downloads page here.

Additionally, since the service is a Java Virtual Machine, I needed to install a Java Runtime Environment located here.

With my host, runtime and libraries in place, it’s time to start the service itself.  This involves a simple command line statement.  Elements show the location of the Chrome WebDriver on the EC2 host and I’ve also created a log file to keep track of any activity.

java -jar -Dwebdriver.chrome.driver=C:\ChromeWebDriver\chromedriver.exe C:\SeleniumServer\selenium-server-standalone-3.0.1.jar -log “C:\\SeleniumServer\SeleniumLog.txt” 

Refactoring the test project

Once the host is available, it’s just a matter of starting the host and telling the framework where it’s located.  This requires the download of an additional NuGet package called OpenQA.Selenium.Remote which gives you access to the RemoteWebDriver class.  Then I updated my Login and InternalLogin methods to use that as the framework’s IWebDriver object instead of the local one.

With these changes in place, my tests passed with flying colors.  While I chose not to run tests in anything but Chrome this time around, adding additional platforms for testing is as easy as adding the drivers to Selenium Server and then updating the DesiredCapabilities argument of the RemoteWebDriver object.

To wrap it all up, I committed my refactor to my SeleniumFramework repo on GitHub.  Please feel free to look at the updated version and pass along any feedback you might have.

Again, I hadn’t expected this series to take as long as it did, but it feels good to bring it to a close with some working code to show for it.  As always, if you have any questions or comments, please feel free to add them here or address them to john@benedettitech.com.

Thanks for looking in!

UI Unit Testing with Selenium – Part 3 – Advanced Webdriver & A Real World Example

Last time, I got into the basics of Webdriver and put together a couple of tests against ServiceNow.  For this post, I’m going to take a look at more advanced uses of Webdriver as well as putting together a framework of shared methods which can be hooked up to unit tests.  This involved going a little off script for the original course, but I think this series might be better served demonstrating application of the actual content rather than repeating it.

The goals that I have for this post will involve creating a new Solution with a Unit Test project as well as a Selenium framework class that can be reused within multiple tests.  Again, I’ll be testing against my private dev instance of ServiceNow, but I think it will be readily apparent how the framework could be extended as needed for other web frameworks.

I began by first creating a new testing project in Visual Studio, called SeleniumFrameworkTests.  Then I added the following tests based on the activities I demonstrated in the previous post.

LoginAsUser
LoginAsSuperUser
CreateIncidentAsUser
CreateIncidentAsSuperUser

I knew I’d want each test to be completely abstracted from the plumbing of ServiceNow, so I kept each test down to three arguments: environment, username and password.  The environment would hold the URL of the instance we’re connecting to.  And the username and password would contain those values for the account role needed to perform the tasks.  Lastly, I created an app.config file to hold the values.

testproject

Next, I created the main framework class called SeleniumFramework.  This framework class would need to include the Selenium and Selenium.Support packages from NuGet.  With that in place, I created the general Login method which accepts the environment, username and password arguments.  Then I copied the login steps from the previous post.  This allowed both the LoginAsUser and LoginAsSuperUser tests to pass.

loginmethod

The CreateIncident methods proved to be a little trickier.  First, each would require it’s own IWebDriver object with a valid login in order to proceed.  It made more sense to create a private method that returns an IWebDriver object for use by the CreateIncident methods.

privatelogin

With that in place, I copied in the CreateIncident steps from the previous post. The CreateIncidentAsUser test then passed but the SuperUser role has a different interface than the base User.  To get that test to pass, I had to create a separate method and tweak the UI names as needed for the test to then pass.

createincident

To wrap it all up, I created a new repo on Github called SeleniumFramework. Please feel free to take it for a spin yourself.   All you’ll need is a demo instance of ServiceNow as well as a copy of Visual Studio Community, both of which are free!

I know this series has taken much longer than I expected. However, I plan to close it out next time with an implementation of Selenium Server, most likely using the above testing project.

As always, if you have any questions or comments, please feel free to add them here or address them to john@benedettitech.com.

Thanks for looking in!

UI Unit Testing with Selenium – Part 2 – Webdriver Basics

Last time, I did a quick run-through of Selenium IDE for Firefox and got acquainted with the interface and commands associated with Selenium.  This time, I’m diving more into the meat of the framework and using Webdriver.

Webdriver is an API for that can be used by various languages (C#, Java, Python, & Ruby are some examples) that allows your tests to be maintained and run directly from code rather than using a recorder.  This allows us to take a more programmatical approach to testing rather than relying on the recorder exclusively.

We will be using Visual Studio for this example.  Firefox is supported right out of the box, but IE and Chrome require a special binary to be staged locally in order for those browsers to be used with Selenium.  This (and others) can be located via links at SeleniumHQ.

Since Chrome is my own preferred browser, I’m glad to move away from Firefox and experiment with something a bit more familiar.  I decided to start with rerunning the test that I created using Selenium IDE previously, then build on that a bit.

One feature that I didn’t mention about Selenium IDE, is the export function.  This creates source code in your chosen framework (C#, Java, etc.) from the Selenium markup code created by the recorder.

seleniumexport

One cool thing about the export is that it intersperses the markup within your code as comments.  This can be very useful when retracing what was done in a recording or for general documentation.

First off, I created a C# console project and installed the Selenium Webdriver plugin from NuGet.  With that in place, I’ve added the export from my previous post to a new project to test with Chrome.  My code is below:

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace WebDriverDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            IWebDriver driver = new ChromeDriver(@”C:\Libraries\”);
            driver.Navigate().GoToUrl(“https://dev20556.service-now.com/navpage.do”);
            driver.SwitchTo().Frame(“gsft_main”);
            driver.FindElement(By.Name(“user_name”)).Click();
            driver.FindElement(By.Id(“user_name”)).Clear();
            driver.FindElement(By.Id(“user_name”)).SendKeys(“USERNAMEGOESHERE”);
            driver.FindElement(By.Id(“user_password”)).Clear();
            driver.FindElement(By.Id(“user_password”)).SendKeys(“PASSWORDGOESHERE”);
            driver.FindElement(By.Id(“sysverb_login”)).Click();
        }
    }
}

This sample using the export from my previous post results in a successful login.  Now to build on it a little bit and create a test Incident:

            driver.FindElement(By.LinkText(“Incidents”)).Click();
            driver.SwitchTo().Frame(“gsft_main”);
            driver.FindElement(By.Id(“new_incident”)).Click();
            SelectElement urgency = new SelectElement(driver.FindElement(By.Name(“IO:5a33d0ef0a0a0b9b007b906f6c589c57”)));
            urgency.SelectByText(“1 – High”);
          driver.FindElement(By.Name(“IO:3f272c500a0a0b990059c24380a2bc02”)).SendKeys(“Creating a test incident.”);

            driver.FindElement(By.Name(“submit_button”)).Click();

Just adding these few extra lines results in a repeatable New Incident test.

incidentsuccess

It’s easy to start to see how this framework can be used to build a library of repeatable tests to automate QA and regression testing.

Link to the Full .NET API : http://seleniumhq.github.io/selenium/docs/api/dotnet/

As I continue to progress through the Pluralsight course, my next post should cover advanced WebDriver concepts and possibly Selenium Server.

As always, if you have any questions or comments, please feel free to add them here or address them to john@benedettitech.com.

Thanks for looking in!

UI Unit Testing with Selenium – Part 1


So, I’m making it through the Selenium Pluralsight course slowly but surely and I’m learning quite a bit so far.

The first part covers a browser plug-in called Selenium IDE.  Available only for Firefox, it’s essentially a session recording tool,  It records what we do in the browser then parses those into commands and then can be played back to act as tests.  To take this out for a spin, I went ahead and installed the plug-in and watched the demo on the course.  Now, we’ll need to find something suitable to test it on.

selenium

There’s a SaaS platform called ServiceNow that I’ve been spending a great deal of time in this year.  Automating testing against this platform from a central host is one of my goals for this experiment.  To test this out, I’ve created a test instance of ServiceNow and a test user.  Also, I’ve installed the Selenium IDE on Firefox so that I can record my session in the platform.

My demo is basically automating a login for my test user.  First I’ll need to create a fresh test case in Selenium.

newtest

Then, I’ll record the steps to the login to get a complete test.

finishedtest

Then I’ll run the test and see if it logs me into the system, which it does.

success

This is just scratching the surface of Selenium and I have more modules in the course to cover.  Next post, I’ll have some additional content from the next module (Selenium Web Driver) and possibly a little more.

As always, if you have any questions or comments, please feel free to add them here or address them to john@benedettitech.com.

Thanks for looking in!

UI Unit Testing with Selenium – An Experiment

It’s been a while since I’ve posted.  Part writers block and part outside obligations.  I know you’ve all been despondent and lost in the meantime.  Sorry about that. 🙂

Something that’s a recurring puzzle for me is adapting unit testing to MVC and SaaS solutions.   The challenges from my point of view are that MVC implies a lot of its functionality.  For example, things in MVC behave in very specific manners based on where they’re located or what they’re named.  Also, MVC classes (models) generally don’t have or need default constructors, so a traditional approach of instantiating a class an running business logic is insufficient.

Then, for SaaS solutions, you may not have sufficient access to the plumbing to build your tests directly, so you’re stuck automating a session through the SaaS provider’s interface and (hopefully) capturing the results that you need.  An approach to MVC might look very similar.

Enter Selenium

Either my Google-fu is weak in this space or there aren’t a lot of options for automating tests in this manner.  One framework that gets a lot of mentions is Selenium, so I’m going to take a stab at it.   I’ve found a few good blog resources but also remember that John Sonmez did a Pluralsight course that seems to be right up my alley.

My plan for this week is to watch the course and play around with the framework against a solution or two, then post about the results.  If the path seems promising, I’ll follow up with some additional content.

As always, if you have any questions or comments, please feel free to add them here or address them to john@benedettitech.com.

Thanks for looking in!