DEV Community

Cover image for Day 31: Stash Keeps What Status Won't Show, and Private Is a Flag, Not a Subnet
Nnamdi Felix Ibe
Nnamdi Felix Ibe

Posted on

Day 31: Stash Keeps What Status Won't Show, and Private Is a Flag, Not a Subnet

Both of today's tasks involved something real that the interface never mentions. Git keeps work in a place that git status will not tell you about. The RDS console wizard builds a resource on your behalf and never says it did. Neither is a bug, and both cost you time the first time you meet them.

One Git task, one AWS task. Park uncommitted work with stash and bring a specific entry back, then create a private MySQL RDS instance on the free tier. The tasks come from the KodeKloud Engineer platform.

Stash: the drawer that nothing points you to

Stash is for the moment when you are halfway through something and have to be somewhere else. A hotfix, a colleague's branch, a review. You do not want a commit that says "wip", so you park it.

cd /usr/src/kodekloudrepos/<repo>

git stash list
# stash@{0}: WIP on master: 3a1f2b9 earlier commit
# stash@{1}: WIP on master: 3a1f2b9 earlier commit

git stash show -p 'stash@{1}'
git stash apply 'stash@{1}'
Enter fullscreen mode Exit fullscreen mode

stash@{0} is the newest and stash@{1} is the one before it, and the bare integer works too, so git stash apply 1 is the same call. The braces need quoting in zsh, which reads them as globbing characters.

Then the step that catches people, including me:

git status
git add .
git commit -m "changes of stash@{1}"
git push origin master
Enter fullscreen mode Exit fullscreen mode

apply restores the working tree, not the index. Your files come back modified, not staged, so a bare git commit -m has nothing to commit. git stash apply --index restores the staged state as well, if that is what you parked.

Two more things worth knowing before you rely on it.

apply and pop are not interchangeable. pop restores the entry and deletes it. apply restores it and leaves it in the list. Use apply when you are not yet certain the restore is clean, then git stash drop once you are. And dropping renumbers everything below it, so never drop entries in a loop by fixed index.

Untracked files are not stashed at all by default. A new file that seems to have vanished into a stash was never in it. git stash push -u includes untracked files, and -a includes ignored ones too.

The part that actually matters, though, is that none of this is visible. A stash is a real commit under refs/stash, but it is not in your branch, not in your log, not in git status, and not pushed anywhere. It is local, and it stays local. Work parked in a stash on a server you lose access to is work you have lost. Treat stash as a few hours of parking, never as storage.

The private RDS instance: the flag, and the thing the wizard did for you

The task read like a console walkthrough. Free tier template, full configuration, MySQL 8.4.x, db.t3.micro, 20 GiB of gp2, autoscaling capped at 22 GiB, private. Doing it on the CLI means translating each of those, and two of them do not translate at all.

"Full configuration" is a console-only creation method. The CLI is always full configuration. "Free tier" is a console preset that means db.t3.micro plus single-AZ, which you pin with --no-multi-az. Storage autoscaling and its maximum threshold collapse into one flag, --max-allocated-storage 22, and passing it is what turns autoscaling on.

And "private" is the interesting one. It is not about which subnet the instance lands in. It is an attribute on the instance itself:

--no-publicly-accessible
Enter fullscreen mode Exit fullscreen mode

That flag is what decides whether RDS gives the instance a public DNS name that resolves to a routable address. Put a database in a private subnet with --publicly-accessible, and you have a private-subnet database that AWS is still advertising publicly.

Then the CLI stopped and told me something the console never would have:

aws rds describe-db-subnet-groups --region us-east-1 --output table
Enter fullscreen mode Exit fullscreen mode

Nothing. There was no DB subnet group in the account, and RDS will not create an instance without one. The console wizard makes one silently while you are choosing an engine. The CLI expects you to have done it.

It also has a requirement that surprises people: the subnet group needs subnets in at least two availability zones, and AWS documents that as applying to Single-AZ deployments too, so the instance can be converted to Multi-AZ later. A single-AZ database still needs a multi-AZ subnet group.

VPC=$(aws ec2 describe-vpcs --region us-east-1 \
  --filters "Name=isDefault,Values=true" \
  --query 'Vpcs[0].VpcId' --output text)

SUBNETS=$(aws ec2 describe-subnets --region us-east-1 \
  --filters "Name=vpc-id,Values=$VPC" \
  --query 'Subnets[].SubnetId' --output text)

aws rds create-db-subnet-group --region us-east-1 \
  --db-subnet-group-name xfusion-rds-subnet-group \
  --db-subnet-group-description "Subnet group for xfusion-rds" \
  --subnet-ids $SUBNETS
Enter fullscreen mode Exit fullscreen mode

$SUBNETS is deliberately unquoted there. --subnet-ids wants a space-separated list, and --output text produces exactly that.

One more habit worth stealing. The task said "8.4.x" without pinning a patch level, so rather than guess, I asked AWS which 8.4 versions are actually orderable on that instance class in that region:

VER=$(aws rds describe-orderable-db-instance-options --region us-east-1 \
  --engine mysql --db-instance-class db.t3.micro \
  --query "OrderableDBInstanceOptions[?starts_with(EngineVersion, '8.4')].EngineVersion" \
  --output text | tr '\t' '\n' | sort -uV | tail -1)
Enter fullscreen mode Exit fullscreen mode

describe-orderable-db-instance-options beats describe-db-engine-versions here, because a version can exist and still not be available on db.t3.micro. And sort -V is version sort, which puts 8.4.11 after 8.4.9. Plain sort would not.

That query cost me a detour first. Written with backticks around the version prefix, it fails:

In function starts_with(), invalid type for value: 8.4,
expected one of: ['string'], received: "number"
Enter fullscreen mode Exit fullscreen mode

In JMESPath, backticks delimit JSON literals, so `8.4` is the number 8.4. String literals use single quotes. Backticks appear to work for most words only because invalid JSON degrades to a string, and they break the moment the content parses as a number, a boolean, or null. Use single quotes for strings every time.

Everything after that was one call and a wait of five to ten minutes with no output, which is normal. Do your discovery during the wait, not before it.

State you have to go looking for

The stash and the missing subnet group are the same shape of problem. Something exists, or does not exist, and the tool in front of you has no opinion about telling you. git status is silent about parked work. The console is silent about the resource it built for you, right up until you try the same thing without it.

So here is the Day 31 question. What is true about your environment right now that nothing on your screen is telling you?

Day 31 down. Sixty-nine to go.

Top comments (0)