Other courses (NOTES)
I also tried to learn Terraform for AWS, because DevOps interests me.
Terraform commands intruduction
Terraform is configured with a .tf command which defines information about the servers you want to provision. To start Terraform, type the command terraform init which initializes the .terraform directory with some provisioner which you defined in the .tf file. For AWS, this is hashicorp AWS. It also creates a lock file which locks the version of the hashicorp AWS provider that you are using so future terraform inits use the same version (keep this file in source control).
Next, you run terraform validate which checks to see if your .tf file is valid. Pretty straightforward. In the example given, the .tf file contains an AMI of the AWS EC2 instance you hope to provision and its type (t2.micro).
The next step is terraform plan which shows what Terraform plans to run to provision the instance you requested. A lot of the instance information si not known now (such as IP address and whatever else). You only know the things you specified, which is the AMI and the EC2 type. At least in this example.
Terraform apply uses the provisioner you downloaded to apply the plan. You should see the EC2 instance created.
Terraform destroy destroys the EC2 instance.
Terraform Config file basics
Resource block type is a server you are going to provision. Multiple block labels potentially for each block. Then arguments.
I also spent a little time learning about Protobuf:
Making an Http JSON API for a Log Record Application
Use a mutex to lock the log. Encode/decode the JSON from the request body and into the response. Put it inside internal folder. JSON is human readable and great which makes it a great choice for public-facing APIs. But internally (like between microservices) you kinda want something faster, more space efficient, checks semantics, cross-platform, versioned, types safety, backwards compatible, and more.
Lastly, I studied Rust:
Some summary
Strings and vecs are for dynamically sized strings/arrays, &str and &[T] are references to dynamic OR fixed size strings/arrays. These references have a size which is why they're called fat pointers. Methods are defined on these slices (mostly). vec! creates a new vector and adds all the elements one by one. It's a little faster than doing it yourself though because it pre-allocates the right number of spaces for the elements.
Rust single ownership forms a tree so there's no way to loop back around.
Python counts the number of references to objects. Assignments increase the reference counter. C++ performs deep copy. Rust moves ownership.