(defmacro <<- [& forms] `(->> ~@(reverse forms)))
Some of the interesting stuff I did, learned or found in the past week.
Christophe Grand shared a mind-blowing little macro a while ago and it showed up on Clojurians slack again: https://clojurians.slack.com/archives/C03S1KBA2/p1642537427215800
(defmacro <<- [& forms] `(->> ~@(reverse forms)))
Check my clojure-experiments to see it in action.
For one module in a Clojure project, I wanted to assert that no other external namespace (except a few white-listed namespaces) depends on anything inside the module.
I decided to use clj-kondo for this task - the essence is capture here: https://github.com/jumarko/clojure-experiments/blob/master/src/clojure_experiments/linters/clj_kondo.clj#L20
;; Tip from borkdude to make this much faster
;; You can also use tools.namespace directly if you're only interested in namespace dependencies.
;; That will be much faster since it only reads the top level ns form
;; Something like: `(clojure.tools.namespace.find/find-ns-decls-in-dir (clojure.java.io/file "src"))`
(defn- analyse-sources!
"Analysis given source directories (a sequence) with clj-kondo
returning the :analysis key from the output."
[source-dirs]
(let [{:keys [analysis] :as _kondo-result}
;; this can take about 4 seconds
(time (clj-kondo/run! {:lint source-dirs
:config {:output {:analysis true}}}))]
analysis))
(defn- package-usages
[{:keys [namespace-usages] :as _kondo-analysis}
package-sym
allowed-usages]
(let [actual-usages (->> namespace-usages
;; filter only usages of given package
(filter #(str/starts-with? (name (:to %))
(name package-sym)))
;; remove usages that come from within the package
(remove #(str/starts-with? (name (:from %))
(name package-sym)))
(map #(select-keys % [:from :to :row :col])))
forbidden-usages (remove (fn [{:keys [from to]}]
(contains? (set (get allowed-usages from))
to))
actual-usages)]
{:actual-usages actual-usages
:forbidden-usages forbidden-usages
:allowed-usages allowed-usages}))
;; this test will likely take 4+ seconds - see `analyse-sources!`
;; It's supposed to fail with this message:
;; There are namespaces that depend on the package but are not allowed to do so
;; expected: (empty? forbidden-usages)
;; actual: (not (empty? ({:from clojure-experiments.four-clojure.086-happy-numbers, :to clojure-experiments.purely-functional.puzzles.util, :row 6, :col 14})))
(deftest ^:slow ns-usages
(let [analysis-result (analyse-sources! ["src"])]
(testing "No namespaces should depend on our package"
(let [whitelisted '{}
{:keys [forbidden-usages]} (package-usages analysis-result
'clojure-experiments.purely-functional
whitelisted)]
(is (empty? forbidden-usages)
"There are namespaces that depend on the package but are not allowed to do so")))))
Using tools.namespace would indeed be much faster but I decided to leverage clj-kondo because it offered me extra information and also the extra running time isn’t a big problem for my test suite (yet).
restclient-mode
in emacs is a cool way to capture and execute HTTP requests.
You can see a nice of it in Emacs Rocks! Episode 15: restclient-mode.
I found that using h in cider-debugger can be really helpful!
Instrument your function, jump to the line you want to start on and press h. Then call the function (perhaps by submitting a web request).
Learn more about Cider Debugger.
Cloudonaut is my favorite resource for learning AWS. I was a subscriber when they still offered paid subscriptions and I’m now a regular follower of stuff they publish.
Recently, they published the AWS Architect Mindset article about the challenges of being an architect on AWS:
You need a broad understanding of the big picture and huge amount of AWS services
and at the same time, you have to know lot of nitty-gritty details too
My highlights from that article:
Amazon EC2 instance network bandwidth: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-network-bandwidth.html
If your EC2 instance has guaranteed 10 Gbit/s connectivity, you only get 5Gbit/s to and from the Internet.
Restriction on email sent using port 25: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-resource-limits.html#port-25-throttle
EC2 blocks outbound traffic on port 25 by default - No matter what your security group says
Amazon Compute Service Level Agreement: https://aws.amazon.com/compute/sla/
If you look closer, 99.99% does not apply to a single instance - assumes that EC2 instances are deployed concurrently across two or more AZs in the same region.
Check Instance-Level SLA ⇒ it’s 99.5% for single instance
I published a short post showing a workaround how to display human friendly datetime
when working with Cloudwatch Insights functions like latest
.
By itself, Cloudwatch only shows unix epoch time in milliseconds which is quite hard to quickly understand.
I watched an interesting webinar Setting up Terraform guardrails with OPA and TFSEC. In particular, tfsec caught my attention and I would like to try it soon on our terraform code.
Check out the video.
A basic but helpful checklist:
Rule 1: Don’t Overlook Developer Credentials - short-lived credentials, secrets management (vaults, etc.)
Rule 2: Always Review Default Configurations - often convenient but not very secure (check toolsl like AWS Security Advisor)
Rule 3: List Publicly Accessible Storage - things like open S3 buckets
Rule 4: Regularly Audit Access Control - least-privilege principle; schedule manual and automated checks
Rule 5: Leverage Network Constructs - granular policies
Rule 6: Make Logging and Monitoring Preventive - effective alerting system
Rule 7: Enrich your Asset Inventory - additional information about ownership, use-case, sensitivity
Rule 8: Prevent Domain Hijacking - Regularly review your DNS and cloud configurations to prevent take-over situations.
Rule 9: A Disaster Recovery Plan is Not Optional - Design a DR program to recover from outside accounts, providers, or locales.
Rule 10: Limit Manual Configurations - infrastructure as code
5 security mechanisms
mkcert tool
Rate limiting & defense in depth
Audit logs & separationg of duties
I finally finished transfer of my blog from wordpress to Cryogen + Cloudflare pages. I’m very happy about this change that took me almost 2 years!
I decided to use AsciiDoc format for my writing, instead of more well known Markdown. It’s more standardized, has more features and it’s extensible.
Check out blog post my AsciiDoc tips mentioned in the blog post. There are also some AsciiDoc resources.
My JavaScript skills are really poor and I sort of hated the language for a long time, but I think it’s worth learning.
I found this nice overview of 5 JavaScript features you should learn:
let and const - var can be re-declared and updated
let cannot be re-declared
const can neither be re-declared nor updated
string interpolation
return `${firstname} ${secondname} is ${age} years old and he lives in ${city}`;
spread operator …
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let arr3 = [ ...arr1, ...arr2 ]
console.log(arr3) // [1, 2, 3, 4, 5, 6]
arrow functions
// instead of this:
function demo(a, b) {
return a + b;
}
// write this:
const demo = (a,b) => a + b;
destructuring
const { name, age, city } = { name: "John", age: 27, city: "Texas" };
Array destructuring is done using square brackets
Apart from these features, you should also learn features such as:
promises - a promise is a proxy for a value not necessarily known when the promise is created
async/await - An async function is a function declared with the async keyword, and the await keyword is permitted within it
Check https://javascript.info/async-await which also shows how to explicitly return a promise
rest operator - …theArgs
params allows a function to accept an indefinite number of arguments as an array,
shorthand properties - when you have a variable which has the same name as a property of the constructed object
The Ten Commandments of Egoless Programming, as originally established in Jerry Weinberg’s book The Psychology of Computer Programming
A quick recap of some of the links mentioned in this post:
my clojure-experiments demonstrating the `<--` macro
My last post about Cloudwatch insights and converting unix timestamps
transfer of my blog from wordpress to Cryogen + Cloudflare pages