Potato Salad

Ingredients;

  • Boil potatoes & carrots, then drain and peel (once cooled)
  • Sweet & sour cucumbers (chopped)
  • Red capsicum
  • Eggs
  • Mayonaise (swiss / good maoy)

Chopped salami (optional)

Starting lead-climbing after doing the lead-course

So, you’ve done the Lead course — congratulations!

We’ve included a few helpful tips to keep in mind as you get started with the skills you’ve learnt;

  • If you are unsure of something ASK. Accidents only take one tiny mistake.
  • Never be afraid to ask for help, or why someone has done something differently. Experienced people are always happy to help.
  • Learn to lead at Arapiles, it is so much better than anywhere else. Once you have done at 20 climbs then perhaps consider different locations. Be aware that the quality of rock is quite variable at the grampians, werribee gorge, and camles hump.
  • Down climbing is a trad climbers best friend.
  • Do not even consider multipitch climbing until you have done at least 10-20 single pitch climbs and a climb takes under 2 hours from start to finish (including racking up and returning to the ground).
  • Avoid doing climbs longer than 30m when you start out. If something goes wrong you can always be lowered to the ground.
  • Climbs that are describe as “bouldery” have tough starts. Do not do these climbs unless you can get lots of gear in down low.
  • If you can’t protect the crux of the climb, DO NOT DO THE CLIMB
  • At least 3 bombproof pieces of gear for an anchor.
  • You are only safe at the top of a climb when the anchor is finished and there is no chance of falling off the edge.
  • If belaying normally from the top, the brake rope is always in the locked off position.
  • Use names when communicating with your seconder/ leader.
  • Gear at feet = More gear (a good time to put in another piece of gear/protection).
  • At crux= More gear (another good time to put some more gear in).
  • Traverse/ gear below over hang = More gear with an extender (as above).
  • Always take more gear than less. It makes you stronger and you are less likely to run out.
  • NEVER GET COMPLACENT. That’s when stuff really really goes wrong.
  • Abseiling is a dangerous activity. Always be on a safety line and triple check everything before you commit to the decent.
  • Triple checking any safety system is probably a very good idea always.
  • You are responsible for yourself and your judgement is your best friend.
  • And finally, NEVER ABSEIL THE MULDOON RAP STATION WitH ONE ROPE. You have been warned

The suggested list at the bottom is a great starting point to plenty of good climbs with good protection and a great place to hone your skills. Remember, when you are first starting out, it’s about refining your skills (placements, anchors, JUDGEMENT), as opposed to climbing hard & your ability (ie. trying the latest silly run out death climb). Get the technical side of things down-pat so that it’s second nature, and harder routes in time will be easier and more safer. Do at LEAST 20 of the climbs listed before contemplating multi-pitch climbing (which generally takes longer, is more committing and is more “in the deep-end” than the single-pitch options).

After 20 of the recommended climbs (ideally at least a few being grade 10), maybe have a look at some of the smaller multi-pitch climbs. Just make sure you can complete a single pitch, from leaving the ground to back on the ground in around 1 – 1.5 hours. This is a fairly good guide that you are becoming efficient in your climbing.

Spend 3 trips at Arapiles learning the ropes before you consider the Grampians (Summerday Valley has great beginner leads). Leave Werribee Gorge and Camels Hump for quite a few months.

Once you have done at least ten leads (that’s yourself actually leading, not just seconding) consider coming along on a lead rescue course. YOU WILL ALSO HAVE TO RUN ONE LEAD TRIP before you can come on the rescue course, but they have to be the easiest trips on the planet to run.

Suggested climbs to start with

Baked sliced potatoes

Ingredients

  • Potatoes
  • 1 cup cream
  • Grated parmesan cheese
  • Granulated garlic
  • Salt

Method

  1. Sprinkle granular garlic & add some butter to the bottom of the pan
  2. Add sliced potatoes
  3. Add a good dash of milk and sprinkle on some caraway seeds
  4. Microwave for 3 mins with glad-wrap on top
  5. Grind some salt over it
  6. Finely grate some parmesan cheese
  7. Add a generous (eg 1 cup) / small tub of pure cream
  8. Bake at 150 degrees until brown
  9. Turn over and sprinkle more grated parmesan cheese, continue baking until browned again

Bitbucket Symfony Security Checker

To implement the symfony security checker as part of your bitbucket pipeline, include the following lines of code in one of the steps.

The first line downloads the Symfony CLI tool, and adds it to the path (so it can be run). The 2nd line actually runs the security-check.

- curl -sS https://get.symfony.com/cli/installer | bash && export PATH="$HOME/.symfony/bin:$PATH"
- symfony check:security

Ref; https://symfony.com/doc/current/setup.html#checking-security-vulnerabilities

Import/Export data from DynamoDB (small amounts)

I use this CLI command for exporting and then later importing data from/to DynamoDB (small amounts of data – eg. upto a few hundred items).

It does take a while to get data back into DynamoDB, as it’s doing it line-by-line, rather than as a batch … but gets the job done!

Export;

aws dynamodb scan --table-name source-table-name --no-paginate > data.json

Import;

cat data.json | jq -c '.Items[]' | while read -r line; do aws dynamodb put-item --table-name destination-table-name --item "$line"; done

This can be done in one line as well;

aws dynamodb scan --table-name source-table-name --no-paginate | jq -c '.Items[]' | while read -r line; do aws dynamodb put-item --table-name destination-table-name --item "$line"; done

Credit goes to; https://github.com/guillaumesmo

Cleaning up old DynamoDB Auto-Scaling Resources

I’ve found a strange problem with cloud-formation roll-backs which don’t automatically remove any Auto Scaling resources you might have setup.

This means then when you next deploy, CloudFormation starts complaining about resources already existing!

To clean these up, you need the following (run from the CLI, using the AWS CLI);

List resources;

aws application-autoscaling describe-scalable-targets --service-namespace dynamodb

From there, de-register (remove) each of the ones which shouldn’t be there;

aws application-autoscaling deregister-scalable-target --service-namespace dynamodb --resource-id "table/myTableName" --scalable-dimension "dynamodb:table:ReadCapacityUnits"

aws application-autoscaling deregister-scalable-target --service-namespace dynamodb --resource-id "table/myTableName" --scalable-dimension "dynamodb:table:WriteCapacityUnits"

That’s it!

AWS Invoking Lambda functions from CLI

aws lambda invoke \
  --function-name <your function name> \
  --payload '"<your json payload>"' \ 
  --cli-binary-format raw-in-base64-out /dev/stdout

The raw-in-base64-out lets you skip having to base64 encode the payload.

The /dev/stdout bit at the end just shows the output on your screen, rather than outputting it to a file and then having to read that file.

Ref;

  • https://docs.aws.amazon.com/cli/latest/reference/lambda/invoke.html
  • https://acloud.guru/forums/aws-lambda/discussion/-Lys1N6wVQCHE6Ucoxvt/getting-error-as-invalid-base64-for-the-same-data-provided-for-the-kinesis-lectu?answer=-M0gBMHWlAYMm9z1cv6i
  • https://stackoverflow.com/questions/47675032/invoking-aws-lambda-without-output-file

Unit-testing Bref lambda handlers

Hopefully this helps someone out there unit-testing Bref lambda consumers (eg. AWS lambda handlers for SNS / EventBridge / SQS, etc) with PHPUnit;

Essentially this includes the consumer (which is essentially a PHP function), and calls the function with array of event-data (in the same format AWS would normally give it).

The function (handler) would then return a response (hopefully with no thrown errors), and any unit-testing on the result would be done.

public function testConsumeUpdatePerson() {
        $handler = include(__DIR__ . '/../bin/consume');

        $data = json_encode([
            'action' => 'update-person',
            'id' => 1234
        ]);
        $overallJson = '{
  "Records": [
    {
      "EventVersion": "1.0",
      "EventSubscriptionArn": "arn:aws:sns:us-east-2:123456678:sns-lambda:abc-123",
      "EventSource": "aws:sns",
      "Sns": {
        "SignatureVersion": "1",
        "Timestamp": "2019-01-02T12:45:07.000Z",
        "Signature": "aaaabbbb/ccccdddd/111111==",
        "SigningCertUrl": "https://sns.us-east-2.amazonaws.com/SimpleNotificationService-aaaabbbb.pem",
        "MessageId": "aaaabbbbb",
        "Message": "' . addslashes($data) . '",
        "MessageAttributes": {
          "Test": {
            "Type": "String",
            "Value": "TestString"
          },
          "TestBinary": {
            "Type": "Binary",
            "Value": "TestBinary"
          }
        },
        "Type": "Notification",
        "UnsubscribeUrl": "https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&amp;SubscriptionArn=arn:aws:sns:us-east-2:111122222:test-lambda:aaaaa-bbbbb",
        "TopicArn" : "arn:aws:sns:ap-southeast-2:1111222222:topic-name-goes-here",
        "Subject": "TestInvoke"
      }
    }
  ]
}';
        $event = json_decode($overallJson, true);

        $response = $handler($event, new Context('', 300, '', ''));
        $this->assertEquals('OK', $response);
    }

More unit-tests can obviously be added below, but the basics of this test that there’s no errors, unhandled exceptions, etc which you hadn’t fully tested otherwise

Serializer – array to Object

To convert from an array (including multi-dimensional arrays) to an object, the following code might help!

Ref; https://symfony.com/doc/current/components/serializer.html

// all callback parameters are optional (you can omit the ones you don't use)
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
$normalizer = new ObjectNormalizer(null, null, null, $extractor);
$serializer = new Serializer(
    [
        $normalizer,
        new ArrayDenormalizer(),
    ]
);

$obj = $serializer->denormalize(
    $data,
    Member::class,
    null,
    [ObjectNormalizer::DISABLE_TYPE_ENFORCEMENT => true]
);

Symfony

This can also be achieved by installing the following packages, which Symfony will pickup & use with it’s serializer;

composer require phpdocumentor/reflection-docblock
composer require symfony/property-info

Then, in your service (or controller);

public function __construct(SerializerInterface $serializer) {
    $this->serializer = $serializer;
}

And in your code;

$obj = $this->serializer->denormalize(
    $rowData,
    Member::class
);

You can also lessen the enforcement of variable-types (strings vs ints) with the following;

$obj = $serializer->denormalize(
    $data,
    Member::class,
    null,
    [ObjectNormalizer::DISABLE_TYPE_ENFORCEMENT => true]
);

Ref; https://symfony.com/doc/current/components/property_info.html