Half-Life: Alyx and the definition of detail

One of Valve’s artists clearly has a sense of humor!

The immersiveness of Half-Life: Alyx owes a lot to the extreme levels of detail Valve’s artists crafted into all of its assets. Each object has its own material which, upon close examination, reveals a wonderful depth of realism. Each object has multiple textures along with a shader to render surfaces that realistically imitate textured metal, flaked paint, grimy and scratched surfaces, plastic parts, printed text, and so on. At one point in the game, you can sit down, pick up a newspaper, and read the whole front-page article (in VR). Even the audio is beautifully multilayered. I could go on, but today what has my attention is a little in-joke that I found on one of the weapons in the game.

The Combine SMG, like all weapons in the game, has a series of upgrades. Each upgrade either adds or replaces parts, making it physically visible and distinctive. One of the upgrades for the Combine SMG adds what appears to be a glowing battery box attached the back of the rifle, from which a glowing cable runs to a laser-like attachment under the barrel. The battery box has some tiny text on it which, due to the texture resolution, is blurry and difficult to read:

Pretty tiny, right? Here’s what I think it says:

n. Abbr. det.

part or item; a particular. See Synonyms at item.
considered individually and in relation to a whole: careful attention to detail.
A minor or inconsequential item or aspect; a minutia: skipped the details to get
A minute or thorough treatment or account: went into detail about his travels.
portion of a work, such as a painting, building, or decorative object,
when considered in isolation.
A representation of such a part or portion: a detail of a Rembrandt portrait illustrating

Though not obvious right away because some sentences are truncated, it’s the definition of the word “detail”. One of Valve’s artists clearly has a sense of humor!

The text appears to be based on the definition in the American Heritage Dictionary, however the “n. Abbr. det.” part indicates that it was likely sourced from one of a few Chinese-English dictionary websites. I enjoy how that gives us just a tiny extra piece of information about the particular artist who playfully chose this text.

AWS: allow an assumed role to assume another role

You may occasionally wish to allow an assumed IAM role, such as a role assumed via an EC2 instance profile, to assume another role. This is described in in Switching to an IAM Role (AWS CLI) as “role chaining“. If we wish for role A to be able to assume role B, for example, we must add a statement to the “trust policy” in role B, like this:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "...",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::000000000000:role/a"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

On the EC2, assumed role A will start out looking something like this:

$ aws sts get-caller-identity
{
    "Account": "000000000000", 
    "UserId": "AROAJQTW5F5O55I5ZXQ24:i-00000000000000000", 
    "Arn": "arn:aws:sts::000000000000:assumed-role/a/i-00000000000000000"
}

Despite the fact that this is an assumed role and looks different from the Principal for role A which we referenced in our trust policy, it will still be allowed to assume role B.

IAM Role Policy for Kinesis “Enhanced Fan-Out” Consumers

When switching to version 2 of the KCL Java library and using the “Enhanced Fan-Out” consumer mode, it was difficult to determine the appropriate IAM policy because the AWS documentation did not mention any differences between the old consumer and the new consumer. However, by trial and error, a policy like the one below (though with your own account id) may be reasonable. Of course, you could also split out specific actions to more specific resources, but this is a reasonable first draft.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:CreateTable",
                "dynamodb:DeleteItem",
                "dynamodb:DescribeTable",
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:Scan",
                "dynamodb:UpdateItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:us-west-2:111111111111:table/my-consumer-name"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "kinesis:DescribeStream",
                "kinesis:DescribeStreamConsumer",
                "kinesis:DescribeStreamSummary",
                "kinesis:GetShardIterator",
                "kinesis:GetRecords",
                "kinesis:ListShards",
                "kinesis:PutRecord",
                "kinesis:PutRecords",
                "kinesis:RegisterStreamConsumer",
                "kinesis:SubscribeToShard"
            ],
            "Resource": [
                "arn:aws:kinesis:us-west-2:111111111111:stream/my-stream-name",
                "arn:aws:kinesis:us-west-2:111111111111:stream/my-stream-name/consumer/my-consumer-name",
                "arn:aws:kinesis:us-west-2:111111111111:stream/my-stream-name/consumer/my-consumer-name:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:PutMetricData"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

Grammar Nazi PSA

“Checkout” is a noun. “Check out” is a verb (specifically a “phrasal verb”).

“Setup” is a noun. “Set up” is a verb.

Bad:

“How to setup X”
“First, setup X”
“Checkout the git repo.”
“For more info, checkout the documentation on the wiki.”

Good:

“How to set up X”
“First, set up X”
“Check out the git repo.”
“For more info, check out the documentation on the wiki.”

Bad:

“That’s a great set up.” (You have a great set which is up?)
“Maybe the check out failed.”

Good:

“That’s a great setup.”
“Maybe the checkout failed.”

Ciphers supported by AWS (classic) ELBs

I recently had some trouble deploying an app to AWS after enabling HTTPS/TLS on the application because the health check was failing. It turned out that because I had also restricted the list of ciphers my app could use (per my organization’s security recommendations), the ELB was unable to connect to the app because it did not support any of my app’s ciphers. Unfortunately, the AWS docs do not explain what ciphers are supported between a classic ELB and the app. So, here’s the current list:

TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (0x0084)
TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (0x0041)
TLS_RSA_WITH_RC4_128_SHA (0x0005)
TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 (0x00a3)
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f)
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x006b)
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 (0x006a)
TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
TLS_DHE_DSS_WITH_AES_256_CBC_SHA (0x0038)
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (0x0088)
TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA (0x0087)
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 (0x00a2)
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x0067)
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 (0x0040)
TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x0032)
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (0x0045)
TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA (0x0044)
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (0x0016)
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA (0x0013)
TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)

A. A. Klaf Calculus Refresher errata

In going through A. Albert Klaf’s Calculus Refresher, republished by Dover, I came across a mistake in Appendix A. The answer to question 7 on page 88 is incorrect. The question is:

7. What are the most economical dimensions of a right circular cylindrical tank made of steel of uniform thickness and of fixed volume = 6,000 cu. ft.?

And the answer given in Appendix A, p377 is:

7. r = h = 12.41 ft

However, that would give:

V = 6004.3392
dA/dr = 78.0307

I believe the correct answer is:

r = 9.8475
h = 19.6949
giving
A = 1827.8966

If you notice any other errors in this book, let me know in the comments.

PMD XPathRule

Getting this exception when creating a custom XPathRule in a PMD ruleset file?

Oct 11, 2016 12:37:05 PM net.sourceforge.pmd.PMD removeBrokenRules
WARNING: Removed misconfigured rule: OldHadoopPackageImport cause: Missing xPath expression

Make sure your rule definition includes the property element and the value element inside it. For example:

    <rule name="OldHadoopPackageImport"
          message="Avoid importing old Hadoop mapred package, use mapreduce package instead"
          language="java"
          class="net.sourceforge.pmd.lang.rule.XPathRule">
        <properties>
            <property name="xpath" description="XPath expression">
                <value>
                    //ImportDeclaration[Name[contains(@Image, 'org.apache.hadoop.mapred')]]
                </value>
            </property>
        </properties>
    </rule>

Docker unable to pull images from Docker Hub registry

In AWS, my Docker-based ElasticBeanstalk apps were repeatedly removing & adding instances. This resulted in many “Adding instance ‘i-465f6382’ to your environment.” type messages. In the docker-events.log the message “Could not reach any registry endpoint” was repeated. I got the same message when running a “sudo docker pull ubuntu” manually on the EC2, even though network connectivity seemed ok.

As it turns out, Docker Hub has deprecated pulls from Docker clients on 1.5 and earlier. See https://blog.docker.com/2015/10/docker-hub-deprecation-1-5/ for more information.

Also, due to a bug in the ElasticBeanstalk console UI, I had to use the EB CLI command “eb config” to trigger an update of the platform.