Monday, November 25, 2024

Creating IAM Role and Assigning it to EC2 Instance requires four steps

locals {
region = "us-west-2"
owner = "<name>"
ami = "ami-XXXXXX"
}

# Setup ECR Roles for EC2
resource "aws_iam_policy" "ecr_policy" {
name = "MyECRPolicy"

policy = jsonencode({
Version : "2012-10-17",
Statement : [
{
Effect : "Allow",
Action : [
"ecr:CompleteLayerUpload",
"ecr:UploadLayerPart",
"ecr:InitiateLayerUpload",
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage",
"ecr:BatchGetImage"
],
Resource : "arn:aws:ecr:us-west-2:#############:repository/<name>/myweb"
},
{
Effect : "Allow",
Action : "ecr:GetAuthorizationToken",
Resource : "*"
}
]
})

tags = {
Name = "ECR Policy"
Owner = local.owner
}
}

resource "aws_iam_role" "ecr_role" {
name = "MyECRRole"
assume_role_policy = jsonencode({
Version : "2012-10-17",
Statement : [{
Effect : "Allow",
Action : [
"sts:AssumeRole"
],
Principal : {
Service : [
"ec2.amazonaws.com"
]
}
}]
})

tags = {
Name = "ECR Role"
Owner = local.owner
}
}

resource "aws_iam_role_policy_attachment" "ecr_policy_attach" {
role = aws_iam_role.ecr_role.name
policy_arn = aws_iam_policy.ecr_policy.arn
}

# Critical Definition
# When you use the AWS Dashboard to create a role, this will automatically
# create an instance profile. But using TF, this field "Instance profile ARN"
# doesn't appear in UI until this is defined.
#
# "An instance profile in AWS is a container for an IAM role that passes role
# information to an EC2 instance when it starts."
#
# "Instance profiles act as a bridge for IAM roles, which define a collection
# of permissions. An EC2 instance profile defines "who" the instance is, and
# then "assumes" the IAM role to gain the necessary permissions"
#
# It is then possible to select the MyECRRole and assign it to the instance
resource "aws_iam_instance_profile" "ecr_instance_profile" {
name = "MyECRInstanceProfile"
role = aws_iam_role.ecr_role.name
}


Tuesday, October 1, 2024

Leetcode Binary Tree Array Format in Golang

In the Binary Tree section of leetcode, they provide an Input array with values used to create a binary tree.

It isn't necessary to reproduce the trees to solve the traversal problems as you can manually build a tree by adding Left and Right nodes manually.

Still using the input data helps to suss out bugs when it fails some tests. The difficulty I ran into was trying to implement a recursive solution when the approach was understanding (with some googling help) that a queue was needed.

Below are my comments and code.

// create binary tree given a leetcode compressed array
// a verbose version of a binary tree would have a NULL_VALUE
// for every node at the full height eg.
//
// 0
// null 2
//
// null null 3 null
// Input = [0, null, 2, null, null, 3]
//
// leetcode BT format is a little more efficient as it will
// skip the 2 lower nulls
//
// Input = [0, null, 2, 3]
// To build the binary tree use a queue that will allow us to
// process each level before continue to the next level.
// When a node is created we add it to the queue. The L/R logic
// proceeds and pops the next value from the Input array.
// If the value is a null, we don't add it to the queue which stops
// further processing on that branch
//
// We loop until the queue is empty.
func (b *BinaryTree) CreateUnsorted(arr []int) {
if len(arr) <= 0 {
fmt.Println("No Elements")
return
}

val, arr := ArrayPop(arr)
b.Root = &TreeNode{Val: val}

queue := []*TreeNode{b.Root}
var node *TreeNode
leftVal := 0
rightVal := 0

for len(queue) > 0 {
node, queue = ArrayPop(queue)

if len(arr) <= 0 {
continue
}
leftVal, arr = ArrayPop(arr)

if leftVal != NULL_VALUE {
node.Left = &TreeNode{Val: leftVal}
queue = append(queue, node.Left)
}

if len(arr) <= 0 {
continue
}
rightVal, arr = ArrayPop(arr)

if rightVal != NULL_VALUE {
node.Right = &TreeNode{Val: rightVal}
queue = append(queue, node.Right)
}
}
}