Text
i’ve moved
i live here now: https://blog.sebastianfromearth.com/
0 notes
Text
swift property observers
Property observers observe and respond to changes in a property’s value. Property observers are called every time a property’s value is set, even if the new value is the same as the property’s current value.
var something: String! = "hellooooo" { didSet { myGroovyMethod() } willSet { myOtherGroovyMethod() } } something = "goodbye"
In the above code snippet, the order of operations are like this:
something is equal to "hellooooo" willSet was called myOtherGroovyMethod() was called something is equal to "goodbye" didSet was called myGroovyMethod() was called
1 note
·
View note
Text
reloading the ui in iOS
setNeedsLayout()
Asynchronous - tells the system that you want it to layout and redraw that view and all of its subviews, when it is time for the update cycle. This is an asynchronous activity, because the method completes and returns immediately, but it isn’t until some later time that the layout and redraw actually happens, and you don’t know when that update cycle will be.
layoutIfNeeded()
Synchronous - tells the system you want a layout and redraw of a view and its subviews, and you want it done immediately without waiting for the update cycle. When the call to this method is complete, the layout has already been adjusted and drawn based on all changes that had been noted prior to the method call.
layoutSubviews()
The default implementation which subclasses can override as needed to perform more precise layout of their subviews. You should never call this method directly, but use the above two instead.
1 note
·
View note
Text
iOS view controller life cycle methods
this first one is only with Objective C, swift also has it but the technique to use it is different
-(void)initWithCoder
if you are using storyboards
func awakefromNib()
if you are generating the view contoller from code
func loadView()
the next one is called only once in the life cycle of viewController, once it has been added to the stack
func viewDidLoad()
while moving to a new ViewController
func viewWillAppear() func viewDidAppear()
and what happens to the old ViewController that was moved away from
func viewWillDisappear() func viewDidDisappear()
0 notes
Text
an easier way to chroot pod
well apparently there's this thing here: http://tinyurl.com/chrootpod.
apiVersion: v1 kind: Pod metadata: name: chrootpod spec: containers: - args: - sleep - "99999" image: busybox imagePullPolicy: Always name: busybox volumeMounts: - mountPath: /realroot name: realroot hostNetwork: true volumes: - hostPath: path: / name: realroot
i haven't tried it, but i think you can just
$ kubectl apply -f https://tinyurl.com/chrootpod
exec into it and bam, node access.
0 notes
Text
note to self about the k8s hpa
that means that if a deployment with like:
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: some-deployment spec: . . template: spec: containers: - name: some-deployment image: some-image:latest imagePullPolicy: Always resources: requests: memory: 100Mi cpu: 0.1 limits: memory: 200Mi cpu: 1 . . --- apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler spec: maxReplicas: 10 minReplicas: 2 scaleTargetRef: apiVersion: extensions/v1beta1 kind: Deployment name: some-deployment targetCPUUtilizationPercentage: 80
the hpa will spin up a new pod when the current deployment is using 80% of 0.1 vcpus. Not 80% of 1 vcpu. If you expect high utlisation, you'll find youself maxing out your maxReplicas super quickly.
0 notes
Text
san certificates with openssl
$ openssl req -new -sha256 -nodes -out some.csr -newkey rsa:2048 -keyout some.key -config some.openssl.cnf
the config file would look something like this...
// some.openssl.cnf [req] default_bits = 2048 prompt = no default_md = sha256 req_extensions = req_ext distinguished_name = dn [ dn ] C=AU O=Some Organisation OU=Dev Ops CN=some.domain.io ST=Victoria L=Melbourne [ req_ext ] subjectAltName = @alt_names [ alt_names ] DNS.1 = some.domain1.io DNS.2 = some.domain2.io DNS.3 = someother.domain.io
0 notes
Text
make an http request with nc
$ printf "GET / HTTP/1.1\r\nUser-Agent: nc/0.0.1\r\nHost: 127.0.0.1\r\nAccept: */*\r\n\r\n" | nc my.groovy.website 80
0 notes
Text
disenchantment
sometimes i feel disenchanted with the state of the tech industry, especially web development...
i came across some blog posts here and here which captures the feeling for me quite accurately
0 notes
Text
terraform order of execution
window.location.replace("https://blog.sebastianfromearth.com/post/20181017122519");
create resource group, create db, create firewall rule.
like this:
> main.tf resource "azurerm_resource_group" "my_groovy_resource_group" { name = "${var.resource_group_name}" location = "${var.location}" } resource "azurerm_mysql_server" "my_groovy_db" { depends_on = ["azurerm_resource_group.my_groovy_resource_group"]
when we run terraform, it'll do it in the order specified:
$ terraform apply . . . module.server.azurerm_resource_group.my_groovy_resource_group: Creating... . . module.server.azurerm_resource_group.my_groovy_resource_group: Creation complete after 1s ... module.server.azurerm_mysql_server.my_groovy_db: Creating... . . module.server.azurerm_mysql_server.my_groovy_db: Creation complete after 4m5s ... module.server.azurerm_mysql_firewall_rule.allow_office: Creating... . . module.server.azurerm_mysql_firewall_rule.allow_office: Creation complete after 16s ... Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
and when you want to destroy it, it'll go in reverse order:
$ terraform destroy . . . module.server.azurerm_mysql_firewall_rule.allow_office: Destroying... . . module.server.azurerm_mysql_firewall_rule.allow_office: Destruction complete after 16s module.server.azurerm_mysql_server.my_groovy_db: Destroying... . . module.server.azurerm_mysql_server.my_groovy_db: Destruction complete after 15s module.server.azurerm_resource_group.my_groovy_resource_group: Destroying... . . module.server.azurerm_resource_group.my_groovy_resource_group: Destruction complete after 47s Destroy complete! Resources: 3 destroyed.
terraform i ❤︎ u
0 notes
Text
terraform variable passing
★ tree . ├── README.md ├── modules │ ├── my_app │ │ ├── provider.tf │ │ ├── main.tf <----------- aaaand this guy │ │ └── variables.tf <--------- and this guy also ├── prod │ ├── backend.tf │ └── main.tf <--------- inside this guy
the variables look like this. they are just some strings:
> prod/main.tf module "my_app" { source = "../modules/my_app" some_var = "abc" some_other_var = "123" }
in the module's variables.tf file, you need to do this, which is like initialising them. good practice is to include a description with the variable.
> modules/my_app/variables.tf variable "some_var" { type = "string" description = "A groovy description about this variable." } variable "some_other_var" { type = "string" description = "Descriptions are awesome." }
and finally, you will be able to use them in the actual module template by putting them into this ${var.some_var} format:
> modules/my_app/main.tf resource "azurerm_mysql_database" "my_groovy_db" { name = "my_groovy_db" resource_group_name = "${var.some_var}" server_name = "${var.some_other_var}" charset = "utf8" collation = "utf8_unicode_ci" }
terraform i ❤︎ u
0 notes
Text
terraform remote backends
★ tree . ├── README.md ├── modules │ ├── my_app │ │ ├── provider.tf │ │ ├── main.tf │ │ └── variables.tf ├── prod │ ├── backend.tf <---------- this one │ └── main.tf > prod/backend.tf terraform { backend "azurerm" { storage_account_name = "my_storage_account" container_name = "my_folder_or_blob_name" key = "the_file_name" resource_group_name = "blah" arm_subscription_id = "xxxEXAMPLE" arm_client_id = "xxxEXAMPLE" arm_tenant_id = "xxxEXAMPLE" } } ★ terraform init -backend-config "arm_client_secret=xxxEXAMPLE"
things to remember: • a remote backend functions as a single point of truth in a system where the repo can exist in multiple places at once. • when working in a team, a remote backend will help to ensure everyone has the latest version of the terraform state. • you must remember to always run terraform init before running a terraform plan/apply in order to sync your local stuff with the remote state.
after running terraform init, the file in the blob on the remote cloud storage will contain the same state contents as appears in your local .terraform/terraform.tfstate file
├── prod │ ├── .terraform │ │ └── terraform.tfstate <-------------- this guy │ ├── backend.tf │ └── main.tf
terraform i ❤︎ u
0 notes
Text
terraform standard module structure
★ tree . ├── README.md ├── modules │ ├── database │ │ ├── main.tf │ │ ├── provider.tf │ │ └── variables.tf │ ├── grants.tf │ ├── server │ │ ├── firewall.tf │ │ ├── main.tf │ │ ├── provider.tf │ │ ├── resource_group.tf │ │ ├── server.tf │ │ └── variables.tf │ └── user │ ├── main.tf │ ├── provider.tf │ ├── users.tf │ └── variables.tf ├── prod1 │ ├── backend.tf │ └── main.tf ├── qa1 │ ├── backend.tf │ └── main.tf └── stg1 ├── backend.tf └── main.tf
things to remember: • modules contain reusable components • enviroment named folders contained module selectors and environment specific variables which are passed into the modules
terraform i ❤︎ u
0 notes
Text
how to get onto a k8s node from a pod
run a busybox deployment:
★ kubectl run busybox --image busybox -- sleep 99999
edit it and add the below things related to: • securityContext (run as root user with privilege escalation) • volumeMounts & volumes (mount the root file system into the pod) • hostNetwork (via the network the k8s node is on)
★ kubectl edit deploy busybox apiVersion: extensions/v1beta1 kind: Deployment metadata: labels: run: busybox name: busybox namespace: default spec: replicas: 1 selector: matchLabels: run: busybox strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate template: metadata: creationTimestamp: null labels: run: busybox spec: containers: - args: - sleep - "99999" image: busybox imagePullPolicy: Always name: busybox resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File . . securityContext: allowPrivilegeEscalation: true runAsUser: 0 volumeMounts: - mountPath: /rootfs name: rootfs volumes: - hostPath: path: / type: "" name: rootfs hostNetwork: true . . dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30
exec into your pod and you'll see this directory called rootfs in the root of the pod:
★ kubectl get pods NAME READY STATUS RESTARTS AGE busybox-5c7f574bd4-96h84 1/1 Running 0 12m ★ kubectl exec -it busybox-5c7f574bd4-96h84 /bin/sh / # ls -l total 40 drwxr-xr-x 2 root root 12288 Jul 31 20:20 bin drwxr-xr-x 5 root root 360 Sep 26 15:14 dev drwxr-xr-x 1 root root 4096 Sep 26 15:14 etc drwxr-xr-x 2 nobody nogroup 4096 Jul 31 20:20 home dr-xr-xr-x 395 root root 0 Sep 26 15:14 proc drwx------ 1 root root 4096 Sep 26 15:14 root drwxr-xr-x 23 root root 4096 Sep 12 06:04 rootfs <-------- THIS GUY dr-xr-xr-x 12 root root 0 Aug 27 11:16 sys drwxrwxrwt 2 root root 4096 Jul 31 20:20 tmp drwxr-xr-x 3 root root 4096 Jul 31 20:20 usr drwxr-xr-x 1 root root 4096 Sep 26 15:14 var
hmmm, what's this?
/ # chroot rootfs root@k8s-node-12345678-2:/#
:O
root@k8s-node-12345678-2:/# ls -l total 88 drwxr-xr-x 2 root root 4096 May 25 06:16 bin drwxr-xr-x 3 root root 4096 Sep 12 06:04 boot drwxr-xr-x 15 root root 3780 Sep 24 09:05 dev drwxr-xr-x 99 root root 4096 Sep 21 06:56 etc drwxr-xr-x 12 root root 4096 Mar 12 2018 home lrwxrwxrwx 1 root root 33 Sep 12 06:04 initrd.img -> boot/initrd.img-4.15.0-1023-azure lrwxrwxrwx 1 root root 33 Sep 12 06:04 initrd.img.old -> boot/initrd.img-4.15.0-1022-azure drwxr-xr-x 22 root root 4096 Mar 9 2018 lib drwxr-xr-x 2 root root 4096 Jan 26 2018 lib64 drwx------ 2 root root 16384 Jan 26 2018 lost+found drwxr-xr-x 2 root root 4096 Jan 26 2018 media drwxr-xr-x 3 root root 4096 Mar 9 2018 mnt drwxr-xr-x 3 root root 4096 Mar 9 2018 opt dr-xr-xr-x 402 root root 0 Aug 27 11:16 proc drwx------ 4 root root 4096 Aug 28 13:38 root drwxr-xr-x 31 root root 1300 Sep 11 08:26 run drwxr-xr-x 2 root root 12288 May 25 06:16 sbin drwxr-xr-x 2 root root 4096 Nov 30 2017 snap drwxr-xr-x 3 root root 4096 Mar 9 2018 srv dr-xr-xr-x 12 root root 0 Aug 27 11:16 sys drwxrwxrwt 8 root root 4096 Sep 26 15:17 tmp drwxr-xr-x 10 root root 4096 Jan 26 2018 usr drwxr-xr-x 13 root root 4096 Jan 26 2018 var lrwxrwxrwx 1 root root 30 Sep 12 06:04 vmlinuz -> boot/vmlinuz-4.15.0-1023-azure lrwxrwxrwx 1 root root 30 Sep 12 06:04 vmlinuz.old -> boot/vmlinuz-4.15.0-1022-azure
:O :O :O
root@k8s-node-12345678-2:/# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 90172dd0edd8 busybox@sha256:cb63aa0641a885f54de20f61d152187419e8f6b159ed11a251a09d115fdff9bd "sleep 99999" 20 minutes ago Up 20 minutes k8s_busybox_busybox-5c7f574bd4-96h84_default_cf6dae51-c19e-11e8-87c4-000d3a389f22_0
so remember that anyone with k8s api perms to create pods can dew it.
★ kubectl delete deploy busybox
0 notes
Text
drain a k8s node properly
$ kubectl drain mygroovynode --delete-local-data --ignore-daemonsets
0 notes
Text
get k8s yaml without the fluff
$ kubectl get deployment my-groovy-app -n groovy-app1 -o yaml
you're gonna get a bunch of superfluous stuff like
apiVersion: extensions/v1beta1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "13" creationTimestamp: 2018-10-02T12:28:29Z generation: 13 labels: app: groovy-app chart: groovy-app-0.1.0 heritage: Tiller release: my-groovy-app name: my-groovy-app namespace: groovy-app1 resourceVersion: "11165279" selfLink: /apis/extensions/v1beta1/namespaces/my-groovy-app/deployments/groovy-app uid: ab250446-c63e-11e8-82d7-0a58ac1f0549 spec: progressDeadlineSeconds: 600 replicas: 2 revisionHistoryLimit: 0 selector: matchLabels: app: groovy-app strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate template: metadata: annotations: checksum/config: e1e82121707809ce3cc1a3d7f0a7c50809619165dd152b73449aa93e2f4b896a creationTimestamp: null labels: app: groovy-app chart: groovy-app-0.1.0 heritage: Tiller release: my-groovy-app spec: containers: - image: some.repo/groovy-app:2.2.1-dev.5.a980b816 imagePullPolicy: Always name: groovy-app resources: limits: cpu: "1" memory: 1Gi requests: cpu: 500m memory: 256Mi terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /etc/nginx/conf.d name: nginx-config dnsPolicy: ClusterFirst imagePullSecrets: - name: some.repo restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 volumes: - configMap: defaultMode: 420 name: groovy-app-proxy name: nginx-config status: availableReplicas: 2 conditions: - lastTransitionTime: 2018-10-02T12:31:24Z lastUpdateTime: 2018-10-02T12:31:24Z message: Deployment has minimum availability. reason: MinimumReplicasAvailable status: "True" type: Available - lastTransitionTime: 2018-10-02T12:28:30Z lastUpdateTime: 2018-10-15T13:03:27Z message: ReplicaSet "groovy-app-79cf57ff86" has successfully progressed. reason: NewReplicaSetAvailable status: "True" type: Progressing observedGeneration: 13 readyReplicas: 2 replicas: 2 updatedReplicas: 2
so much fluff, like the status, selfLink, uid, resourceVersion, creationTimestamp, generation, checksum/config.
we can get it without a lot of this stuff with the export flag
$ kubectl get deployment my-groovy-app -n groovy-app1 -o yaml --export
and you'll get it like this
apiVersion: extensions/v1beta1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "13" creationTimestamp: null generation: 1 labels: app: groovy-app chart: groovy-app-0.1.0 heritage: Tiller release: my-groovy-app name: my-groovy-app selfLink: /apis/extensions/v1beta1/namespaces/my-groovy-app/deployments/groovy-app spec: progressDeadlineSeconds: 600 replicas: 2 revisionHistoryLimit: 0 selector: matchLabels: app: groovy-app strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate template: metadata: annotations: checksum/config: e1e82121707809ce3cc1a3d7f0a7c50809619165dd152b73449aa93e2f4b896a creationTimestamp: null labels: app: groovy-app chart: groovy-app-0.1.0 heritage: Tiller release: my-groovy-app spec: containers: - image: some.repo/groovy-app:2.2.1-dev.5.a980b816 imagePullPolicy: Always name: groovy-app resources: limits: cpu: "1" memory: 1Gi requests: cpu: 500m memory: 256Mi terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /etc/nginx/conf.d name: nginx-config dnsPolicy: ClusterFirst imagePullSecrets: - name: some.repo restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 volumes: - configMap: defaultMode: 420 name: groovy-app-proxy name: nginx-config status: {}
0 notes
Text
dynamic anonymous classes & functions in python
>>> class X(object): ... a = 1 ... >>> print X.a 1
but an anonymous one also like this:
>>> X = type('X', (object,), dict(a=1)) >>> print X.a 1
you can create a function like this:
>>> def double(x): ... return x*2 ... >>> print double(2) 4
but an anonymous one also like this:
>>> double = lambda x: x * 2 >>> print double(2) 4
kewl
0 notes