Posts

terraform import existing resources - not quite with 1.5.x with generated output

Image
Terraform import can be quite interesting thing to do. So let's start with us trying to import a storage account. So we will start off using hcl import statement to import this.  provider "azurerm" {   features {} } resource "azurerm_storage_account" "imported_storage" {   name                     = " saforimort "   resource_group_name       = " mytest-kv-rg "   location                 = " australiaeast "   account_tier             = " Standard "   account_replication_type = " LRS " } import {   to = azurerm_storage_account . imported_storage   id = " /subscriptions/your-subscription-id/resourceGroups/ mytest-kv-rg/providers/Microsoft.Storage/storageAccounts/saforimort " } As you can see here, we are trying to import to  "azurerm_storage_account" "imported_storage" . and we just ne...

opencode - creating plugin and distributing it via npm

Image
We can easily create a plugin for opencode. In this example, we are just going to write a simple output. First we need to create a nodejs project using the following code. Please refer to this code repo here for typescript setup and other codes.  https://github.com/kepungnzai/appcoreopc-num-mastery. In this code, the most important thing is it must inherit from Plugin (quite important) otherwise your agent might not be able to figur out. import { type Plugin } from " @opencode-ai/plugin " import { tool } from " @opencode-ai/plugin/tool " export const AppcoreopcNumMastery : Plugin = async () => {   const myTool = tool ( {     description : " A simple plugin. " ,     args : {       query : tool . schema . string () . describe ( " Question or topic to submit to Google AI Mode " ) ,       timeout : tool . schema . number () . min ( 5 ) . max ( 120 ) . optional () . describe ( " Timeout in seconds (...

opencode creating plugins and exposing it via opencode command line

Image
 Let's create a plugin that you can call from opencode command interface for example by typing  /custom-plugin  to get opencode to execute your plugin. To do that, we need to create a plugin and then create command that goes into opencode.json The plugin  The plugin code - you need to create a folder ".opencode/plugins/custom-tools.ts".  import { type Plugin , tool } from " @opencode-ai/plugin " export const CustomToolsPlugin : Plugin = async ( ctx ) => {   return {     tool : {       mymagictool : tool ( {         description : " This is a custom tool " ,         args : {           foo : tool . schema . string () ,         },         async execute ( args , context ) {           const { directory , worktree } = context           return ` Hello ${ ...

opencode creating tools

Image
We can easily extend opencode to support custom tools and plugins. We will cover plugin which is essentially npm packages you publish.  To create a custom tools, we create a folder called ".opencode/tools/hello.ts and in this file we have the following code.  hello.ts import { tool } from " @opencode-ai/plugin " export const sayhello = tool ( {   description : " say hello multiple times " ,   args : {       name : tool . schema . string () . describe ( " Name to greet " )   },   async execute ( args ) {     return ` Hello, ${ args . name } ! Hello again, ${ args . name } ! `   }, } )   Next, fire opencode and then you can start to use it and you will get the following output. This is just an example.

opencode setting up skills

opencode can be extended with skills. To setup, go and create opencode.json config file.  In the folder that you're trying to fun opencode, create a file called opencode.json and then place the following content in there. It will setup obra superpowers and opencode-devcontainers.  superpowers is a skills or plugin that supports your model application development. It helps with writting plans, request code review and brain storming.  devcontainers provide workspace isolations by running your code on a container and not touching the host.  To install all these superpowers above, add this to your opencode.json file. opencode.json  {   " $schema " : " https://opencode.ai/config.json " ,   " plugin " : [ " superpowers@git+https://github.com/obra/superpowers.git " , " opencode-devcontainers " ] } More info https://github.com/athal7/opencode-devcontainers https://github.com/obra/superpowers

opencode using qwen 3.6 code for free

Image
Opencode supports qwen 3.6 and you can use it for free. Here is how you can use it. Download and install opencode. curl -fsSL https://opencode.ai/install | bash Then you can fire it up in your bash terminal.  Press / (slash) and then choose your qwen 3.6 as your model. And that's it.   Give it a go, ask it to coding :- 

Google ADK - taking a look at LLMAgent, Agent, AgentTool, SubAgent, SequentialAgent and ParrallelAgent

This covers some confusion around agent in Google ADK. So what is the differences between LLMAgent, Agent, SequentialAgent and ParallelAgent?  LLMAgent is used for reasoning, understanding your intention, making decision and ability to interact with tools.  To use LlmAgent here is an example capital_agent = LlmAgent ( model = "gemini-2.5-flash" , name = "capital_agent" , description = "Answers user questions about the capital city of a given country." # instruction and tools will be added next ) Agent is an alis for LLMAgent.  SequentialAgent on the other hand are pre-defined sequential workflow to be carried out by an orchestration agent. In this case, it would be Agent / LLMAgent.  Code example of sequentialAgent can be shown here  location_strategy_pipeline = SequentialAgent (     name = " LocationStrategyPipeline " ,     description = """ Comprehensive retail location strategy analysis pipeline. "...

bicep using user defined function

User defined function can be quite handy to help us some save time. Here is an example of how we can defned user defined function (like in golang) func buildResourceName ( prefix string , env string , suffix string ) string =>   toLower ( ' ${ prefix } - ${ env } - ${ suffix } ' ) And to use it we simple call it here in our storage container examples:-  resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-01-01' = [ for name in containers : {   parent : blobService   name : buildResourceName ( name , 'dev' , 'aue' )   properties : {     publicAccess : 'None'     metadata : {       project : 'audit-2026'     }   } }] You can get all the bicep function here https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-functions Placing your function in another file  You can place all your function in a separate file and import it in.  functions....

bicep using if condition and for keyword

We can use if to control whether we should create a resource in bicep. For example, we have this code here and you can see we are using "if" to evaluate if we should be creating resources. resource container 'Microsoft.Storage/ storageAccounts/blobServices/containers@2023-01-01' = if ( deploy ) {   parent : blobService   name : name   properties : {     publicAccess : 'None'     metadata : {       project : 'audit-2026'     }   } } And then we can use "for" to create multiple container, for example, here we are using for and looping our array called containers to create multiple container in our storage account. param containers array = [   'container1'   'container2'   'container3' ] resource container 'Microsoft.Storage/ storageAccounts/blobServices/containers@2023-01-01' = [ for name in containers : {   parent : blobService   name : name   properties : {     publicAcc...

bicep working with existing resources and creating additional resources out of it

Image
We can use bicep with existing resource. Let's say we have a storage account called " mystorage2026jw To do that can use existing block. Bicep is very particular about placement of the curly braces after the "equal" = sign.  Otherwise you will get BCP-007 error  storage-account.bicep param resourceName string = 'mytest-kv-rg' param name string = 'mystorage2026jw' resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' existing = {   name : name   scope : resourceGroup ( resourceName ) } output id string = storageAccount . id output currentStorageAccountName string = storageAccount . name Running az bicep to validate our code is good az bicep build --file storage-account.bicep To see your what-if plan   az deployment group what-if -g mytest-kv-rg --template-file storage-account.bicep --query "properties.outputs" And to run the actual deployment, you do   az deployment group create -g mytest-kv-rg --templ...

terraform provider alias

Terraform provider alias allow us to have different configuration when provision resources. In Azure term, that would be creating different resources using different subscriptions. Let's illustate this quickly.  Here we are configuring provider with different subscriptions  # Default Provider (Subscription A) provider "azurerm" {   features {}   subscription_id = " 00000000-0000-0000-0000-000000000000 " } # Secondary Provider (Subscription B) provider "azurerm" {   alias           = " sub_b "   features {}   subscription_id = " 11111111-1111-1111-1111-111111111111 " } And to use this provider here, we can try to create a resource group. resource "azurerm_resource_group" "rg_in_sub_a" {   name     = " primary-resources "   location = " East US "   # No provider specified, so it uses the default } resource "azurerm_resource_group" "rg_in_sub_b" {   provi...

terraform move code block - better way to let terraform know you have moved your resources

Image
 Sometimes we refactor our terraform code and move the basic terraform code  Let's say we have the following code  # main.tf (Root level) resource "azurerm_storage_account" "old_storage" {   name                     = " mystorage2026 "   resource_group_name       = " my-rg "   location                 = " East US "   account_tier             = " Standard "   account_replication_type = " LRS " } And then we refactor our code to the following code structure  The Module Code (modules/storage/main.tf) Notice that inside the module, I've given the resource a new local name: modular_storage. resource "azurerm_storage_account" "old_storage" {   name                     = " mystorage2026jw "   resource_group_name       = " m...