diff --git a/examples/cloud-init/evidently-ui.s3.yml b/examples/cloud-init/evidently-ui.s3.yml
new file mode 100644
index 0000000..0e275d3
--- /dev/null
+++ b/examples/cloud-init/evidently-ui.s3.yml
@@ -0,0 +1,76 @@
+#cloud-config
+
+# Tested on:
+# - Amazon Linux 2023
+
+bootcmd:
+ # `cloud-init` has issues with `firewall-cmd`, using the offline version.
+ - firewall-offline-cmd --add-port='8000/tcp' --zone='public'
+
+users:
+ - default
+ - evidently
+
+packages:
+ - make
+
+write_files:
+ - path: /home/evidently/requirements.txt
+ owner: evidently:evidently
+ defer: true
+ content: |
+ evidently[llm]==0.4.37
+ tracely==0.1.0
+ s3fs==2024.9.0
+ - path: /home/evidently/Makefile
+ owner: evidently:evidently
+ defer: true
+ content:
+ # make sure to keep the tab characters in the targets' definitions
+ |
+ #!/usr/bin/env make
+
+ override venv ?= ${HOME}/venv
+
+ create-venv: override python_version ?= 3.9
+ create-venv: python_executable = ${shell which --tty-only --show-dot --show-tilde 'python${python_version}'}
+ create-venv: ${python_executable}
+ @${python_executable} -m 'venv' '${venv}'
+ @${venv}/bin/pip --require-virtualenv install -r 'requirements.txt'
+
+ recreate-venv:
+ @rm -rf '${venv}'
+ @${MAKE} create-venv
+
+ start-evidently-ui: override host ?= 0.0.0.0
+ start-evidently-ui: override port ?= 8000
+ start-evidently-ui: override workspace ?= s3://evidently-ui/workspace
+ start-evidently-ui: create-venv ${venv}/bin/evidently
+ @${venv}/bin/evidently ui --host='${host}' --port='${port}' --workspace='${workspace}'
+ - path: /etc/systemd/system/evidently-ui.service
+ owner: root:root
+ permissions: 0755
+ defer: true
+ content: |
+ [Unit]
+ Description=Evidently UI
+ Documentation=https://docs.evidentlyai.com/
+ Wants=network-online.target
+ After=network-online.target
+
+ [Service]
+ SyslogIdentifier=evidently-ui
+ Type=simple
+ User=evidently
+ Group=evidently
+ WorkingDirectory=/home/evidently
+ ExecStart=/usr/bin/env make start-evidently-ui
+ Restart=always
+
+ [Install]
+ WantedBy=multi-user.target
+
+runcmd:
+ - systemctl reload 'firewalld.service'
+ - systemctl daemon-reload
+ - systemctl enable --now 'evidently-ui.service'
diff --git a/examples/pulumi/aws/ec2 instance/Pulumi.any.yaml b/examples/pulumi/aws/ec2 instance/Pulumi.any.yaml
deleted file mode 100644
index 9419678..0000000
--- a/examples/pulumi/aws/ec2 instance/Pulumi.any.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-encryptionsalt: v1:55yDA5Kuyzs=:v1:+kFXkziA9Bd7nNZQ:OSBtNRAVCGBXwzTtHOGA5Ti9Dz+FTQ==
-config:
- aws:region: eu-west-1
- aws:defaultTags:
- tags:
- ManagedByPulumi: true
- Owner: "somebody@example.com"
- PulumiProject: ec2-instance
diff --git a/examples/pulumi/aws/ec2 instance/Pulumi.yaml b/examples/pulumi/aws/ec2 instance/Pulumi.yaml
deleted file mode 100644
index 89f46da..0000000
--- a/examples/pulumi/aws/ec2 instance/Pulumi.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-name: ec2-instance
-runtime: nodejs
-description: AWS EC2 instance example
-config:
- pulumi:tags:
- value:
- pulumi:template: aws-typescript
-backend:
- url: file://.
diff --git a/examples/pulumi/aws/ec2 instance/index.ts b/examples/pulumi/aws/ec2 instance/index.ts
deleted file mode 100644
index 297c0ed..0000000
--- a/examples/pulumi/aws/ec2 instance/index.ts
+++ /dev/null
@@ -1,123 +0,0 @@
-import * as aws from "@pulumi/aws";
-import * as cloudinit from "@pulumi/cloudinit";
-import * as yaml from "yaml";
-
-const ami = aws.ec2.getAmiOutput({
- owners: [ "amazon", ],
- nameRegex: "^al2023-ami-2023.*",
- filters: [
- {
- name: "architecture",
- values: [ "arm64" ],
- },
- {
- name: "state",
- values: [ "available" ],
- },
- ],
- mostRecent: true,
-});
-const keyPair = aws.ec2.getKeyPairOutput({ keyName: "somebody-ec2Instances" });
-const subnet = aws.ec2.getSubnetOutput({
- filters: [{
- name: "tag:Name",
- values: [ "Private C" ],
- }],
-});
-
-const securityGroup = new aws.ec2.SecurityGroup(
- "ec2-instance-example",
- {
- name: "Ec2InstanceExample",
- description: "Regulate communications to and from the EC2 Instance",
- tags: {
- Name: "EC2 Instance Example",
- },
- },
-);
-const role = new aws.iam.Role(
- "ec2-instance-example",
- {
- name: "Ec2InstanceExample",
- assumeRolePolicy: JSON.stringify({
- Version: "2012-10-17",
- Statement: [{
- Effect: "Allow",
- Action: "sts:AssumeRole",
- Principal: {
- Service: "ec2.amazonaws.com",
- },
- }],
- }),
- managedPolicyArns: [ "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" ],
- },
-);
-const instanceProfile = new aws.iam.InstanceProfile(
- "ec2-instance-example",
- {
- name: "Ec2InstanceExample",
- role: role.name,
- },
-);
-const userData = new cloudinit.Config(
- "ec2-instance-example",
- {
- gzip: true,
- base64Encode: true,
- parts: [
- {
- // only useful on minimal al2023 base images or other images with no aws-ssm
- contentType: "text/cloud-config",
- content: yaml.stringify({
- package_upgrade: false,
- packages: [ "amazon-ssm-agent" ],
- runcmd: [
- "systemctl daemon-reload",
- "systemctl enable --now 'amazon-ssm-agent.service'",
- ]
- }),
- filename: "cloud-config.managed-by.ssm.yml",
- },
- {
- contentType: "text/cloud-config",
- content: yaml.stringify({
- package_upgrade: false,
- packages: [ "python" ],
- }),
- filename: "cloud-config.managed-by.ansible.yml",
- mergeType: "dict(recurse_array,no_replace)+list(append)",
- },
- ],
- },
-);
-new aws.ec2.Instance(
- "ec2-instance-example",
- {
- ami: ami.apply(ami => ami.id),
- iamInstanceProfile: instanceProfile.name,
- instanceType: "t4g.small",
- keyName: keyPair.apply(keyPair => keyPair.keyName!),
- rootBlockDevice: {
- volumeType: "gp3",
- volumeSize: 20,
- tags: {
- Description: "Instance root disk",
- Name: "EC2 Instance Example",
- },
- },
- subnetId: subnet.apply(subnet => subnet.id),
- tags: {
- Name: "EC2 Instance Example",
- ManagedBySsm: "true",
- ManagedByAnsible: "true",
- },
- userData: userData.rendered,
- vpcSecurityGroupIds: [ securityGroup.id ],
- },
- {
- ignoreChanges: [
- // avoid being replaced just because a new version of the base image came out
- "ami",
- ],
- }
-);
diff --git a/examples/pulumi/aws/ec2 instance/.env.fish b/examples/pulumi/aws/evidently-ui on ec2 instance via alb/.env.fish
similarity index 100%
rename from examples/pulumi/aws/ec2 instance/.env.fish
rename to examples/pulumi/aws/evidently-ui on ec2 instance via alb/.env.fish
diff --git a/examples/pulumi/aws/ec2 instance/.gitignore b/examples/pulumi/aws/evidently-ui on ec2 instance via alb/.gitignore
similarity index 100%
rename from examples/pulumi/aws/ec2 instance/.gitignore
rename to examples/pulumi/aws/evidently-ui on ec2 instance via alb/.gitignore
diff --git a/examples/pulumi/aws/evidently-ui on ec2 instance via alb/Pulumi.any.yaml b/examples/pulumi/aws/evidently-ui on ec2 instance via alb/Pulumi.any.yaml
new file mode 100644
index 0000000..1bba04a
--- /dev/null
+++ b/examples/pulumi/aws/evidently-ui on ec2 instance via alb/Pulumi.any.yaml
@@ -0,0 +1,4 @@
+---
+encryptionsalt: v1:pAW9r3TNSV0=:v1:WNIhJ97VgKWPVLTi:IypZBR+LreWLhasHqWGTNCuabKf3Ew==
+config:
+ aws:region: eu-west-1
diff --git a/examples/pulumi/aws/evidently-ui on ec2 instance via alb/Pulumi.yaml b/examples/pulumi/aws/evidently-ui on ec2 instance via alb/Pulumi.yaml
new file mode 100644
index 0000000..7518fbd
--- /dev/null
+++ b/examples/pulumi/aws/evidently-ui on ec2 instance via alb/Pulumi.yaml
@@ -0,0 +1,11 @@
+---
+name: evidently-ui-on-ec2-via-alb
+runtime:
+ name: nodejs
+ options:
+ packagemanager: npm
+description: 'AWS example: Evidently-UI on EC2 instance via ALB'
+config:
+ pulumi:tags:
+ value:
+ pulumi:template: aws-typescript
diff --git a/examples/pulumi/aws/evidently-ui on ec2 instance via alb/cloud-config.evidently-ui.yml b/examples/pulumi/aws/evidently-ui on ec2 instance via alb/cloud-config.evidently-ui.yml
new file mode 100644
index 0000000..e081fea
--- /dev/null
+++ b/examples/pulumi/aws/evidently-ui on ec2 instance via alb/cloud-config.evidently-ui.yml
@@ -0,0 +1,85 @@
+#cloud-config
+
+# Tested on:
+# - Amazon Linux 2023
+
+bootcmd:
+ # `cloud-init` has issues with `firewall-cmd`, using the offline version.
+ - firewall-offline-cmd --add-port='8000/tcp' --zone='public'
+
+users:
+ - default
+ - evidently
+
+packages:
+ - make
+
+write_files:
+ - path: /home/evidently/requirements.txt
+ owner: evidently:evidently
+ defer: true
+ content: |
+ evidently[llm]==0.4.37
+ tracely==0.1.0
+ s3fs==2024.9.0
+ - path: /home/evidently/Makefile
+ owner: evidently:evidently
+ defer: true
+ content:
+ # make sure to keep the tab characters in the targets' definitions
+ |
+ #!/usr/bin/env make
+
+ # '/tmp' is on tmpfs (uses and is limited by the instance's RAM)
+ # Use a local 'tmp' directory for PIP to avoid exhausting the space during installation
+
+ override tmpdir ?= ${HOME}/tmp
+ override venv ?= ${HOME}/venv
+
+ create-venv: override python_version ?= 3
+ create-venv: python_executable = ${shell which --tty-only --show-dot --show-tilde 'python${python_version}'}
+ create-venv: ${python_executable}
+ @mkdir -p ${tmpdir}
+ @${python_executable} -m 'venv' '${venv}'
+ @TMPDIR=${tmpdir} ${venv}/bin/pip --require-virtualenv install -r 'requirements.txt'
+
+ recreate-venv:
+ @rm -rf '${venv}'
+ @${MAKE} create-venv
+
+ update-venv: ${venv}/bin/pip
+ @${venv}/bin/pip freeze -l --require-virtualenv | sed 's/==/>=/' \
+ | xargs ${venv}/bin/pip --require-virtualenv install -U
+
+ start-evidently-ui: override host ?= 0.0.0.0
+ start-evidently-ui: override port ?= 8000
+ start-evidently-ui: override workspace ?= s3://evidentlyUi/workspace
+ start-evidently-ui: create-venv ${venv}/bin/evidently
+ @${venv}/bin/evidently ui --host='${host}' --port='${port}' --workspace='${workspace}'
+ - path: /etc/systemd/system/evidently-ui.service
+ owner: root:root
+ permissions: 0755
+ defer: true
+ content: |
+ [Unit]
+ Description=Evidently UI
+ Documentation=https://docs.evidentlyai.com/
+ Wants=network-online.target
+ After=network-online.target
+
+ [Service]
+ Type=simple
+ User=evidently
+ Group=evidently
+ WorkingDirectory=/home/evidently
+ ExecStart=/usr/bin/env make start-evidently-ui
+ SyslogIdentifier=evidently-ui
+ Restart=always
+
+ [Install]
+ WantedBy=multi-user.target
+
+runcmd:
+ - systemctl reload 'firewalld.service'
+ - systemctl daemon-reload
+ - systemctl enable --now 'evidently-ui.service'
diff --git a/examples/pulumi/aws/evidently-ui on ec2 instance via alb/index.ts b/examples/pulumi/aws/evidently-ui on ec2 instance via alb/index.ts
new file mode 100644
index 0000000..9e11098
--- /dev/null
+++ b/examples/pulumi/aws/evidently-ui on ec2 instance via alb/index.ts
@@ -0,0 +1,291 @@
+import * as aws from "@pulumi/aws";
+import * as cloudinit from "@pulumi/cloudinit";
+import * as fs from "fs";
+import * as pulumi from "@pulumi/pulumi";
+
+/**
+ * EvidentlyUi requirements - start
+ * -------------------------------------
+ */
+
+const evidentlyUi_s3bucket = new aws.s3.Bucket(
+ "evidentlyUi",
+ { bucket: "evidentlyUi" },
+);
+
+const evidentlyUi_securityGroup_internal = new aws.ec2.SecurityGroup(
+ "evidentlyUi",
+ {
+ name: "EvidentlyUiInternal",
+ tags: { Name: "EvidentlyUiInternal" },
+ ingress: [{
+ description: "Allow connections between ALB and instance",
+ self: true,
+ protocol: "tcp",
+ fromPort: 8000,
+ toPort: 8000,
+ }],
+ egress: [{
+ cidrBlocks: [ "0.0.0.0/0" ],
+ protocol: "-1",
+ fromPort: 0,
+ toPort: 0,
+ }],
+ },
+);
+
+const evidentlyUi_securityGroup_external = new aws.ec2.SecurityGroup(
+ "evidentlyUi-external",
+ {
+ name: "EvidentlyUiExternal",
+ tags: { Name: "EvidentlyUiExternal" },
+ ingress: [
+ {
+ description: "Allow connections to the ALB from outside via HTTP",
+ cidrBlocks: [ "0.0.0.0/0" ],
+ protocol: "tcp",
+ fromPort: 80,
+ toPort: 80,
+ },
+ {
+ description: "Allow connections to the ALB from outside via HTTPS",
+ cidrBlocks: [ "0.0.0.0/0" ],
+ protocol: "tcp",
+ fromPort: 443,
+ toPort: 443,
+ },
+ ],
+ egress: [{
+ cidrBlocks: [ "0.0.0.0/0" ],
+ protocol: "-1",
+ fromPort: 0,
+ toPort: 0,
+ }],
+ },
+);
+
+const evidentlyUi_publicSubnet_output = aws.ec2.getSubnetOutput({
+ filters: [{
+ name: "tag:Name",
+ values: [ "Public Subnet in AZ B" ],
+ }],
+});
+
+/**
+ * -------------------------------------
+ * EvidentlyUi requirements - end
+ */
+
+/**
+ * EC2 Instance - start
+ * -------------------------------------
+ */
+
+const evidentlyUi_instanceAmi_output = aws.ec2.getAmiOutput({
+ owners: [ "amazon", ],
+ nameRegex: "^al2023-ami-2023.*",
+ filters: [
+ {
+ name: "architecture",
+ values: [ "arm64" ],
+ },
+ {
+ name: "state",
+ values: [ "available" ],
+ },
+ ],
+ mostRecent: true,
+});
+
+const evidentlyUi_instanceSubnet_output = aws.ec2.getSubnetOutput({
+ filters: [{
+ name: "tag:Name",
+ values: [ "Private Subnet in AZ C" ],
+ }],
+});
+
+const evidentlyUi_instanceKeyPair = new aws.ec2.KeyPair(
+ "evidentlyUi",
+ {
+ keyName: "EvidentlyUi",
+ publicKey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA1CBr/1GqUX+/rUR00TK34+2sMWbRNkqbckGvYmtypu openpgp:0xE742BC48",
+ },
+);
+
+const evidentlyUi_instanceRole = evidentlyUi_s3bucket.arn.apply(
+ bucketArn => new aws.iam.Role(
+ "evidentlyUi-instance",
+ {
+ name: "EvidentlyUiInstanceRole",
+ assumeRolePolicy: JSON.stringify({
+ Version: "2012-10-17",
+ Statement: [{
+ Effect: "Allow",
+ Principal: { Service: "ec2.amazonaws.com" },
+ Action: "sts:AssumeRole",
+ }],
+ }),
+ inlinePolicies: [{
+ name: "AllowManagingOwnBucket",
+ policy: JSON.stringify({
+ Version: "2012-10-17",
+ Statement: [{
+ Effect: "Allow",
+ Action: "s3:*",
+ Resource: [
+ `${bucketArn}`,
+ `${bucketArn}/*`,
+ ],
+ }],
+ }),
+ }],
+ },
+ ),
+);
+
+const evidentlyUi_instanceProfile = new aws.iam.InstanceProfile(
+ "evidentlyUi-ec2Instance",
+ {
+ name: "EvidentlyUiInstanceProfile",
+ role: evidentlyUi_instanceRole.name,
+ },
+);
+
+const evidentlyUi_instanceUserData = new cloudinit.Config(
+ "evidentlyUi-instance",
+ {
+ gzip: true,
+ base64Encode: true,
+ parts: [{
+ contentType: "text/cloud-config",
+ content: fs.readFileSync("cloud-config.evidently-ui.yml", "utf8"),
+ filename: "cloud-config.evidently-ui.yml",
+ }],
+ },
+);
+
+const evidentlyUi_instance = new aws.ec2.Instance(
+ "evidentlyUi",
+ {
+ ami: evidentlyUi_instanceAmi_output.id,
+ iamInstanceProfile: evidentlyUi_instanceProfile.name,
+ instanceType: "t4g.micro",
+ keyName: evidentlyUi_instanceKeyPair.keyName!,
+ rootBlockDevice: {
+ volumeType: "gp3",
+ volumeSize: 20,
+ tags: {
+ Description: "Instance root disk",
+ Name: "EvidentlyUi-instanceRootDisk",
+ },
+ },
+ subnetId: evidentlyUi_instanceSubnet_output.id,
+ tags: {
+ Name: "EvidentlyUi",
+ ManagedBySsm: "true",
+ ManagedByAnsible: "true",
+ },
+ userData: evidentlyUi_instanceUserData.rendered,
+ userDataReplaceOnChange: true,
+ vpcSecurityGroupIds: [ evidentlyUi_securityGroup_internal.id ],
+ },
+ {
+ ignoreChanges: [
+ "ami", // avoid replacing just because a new version of the base image came out
+ ],
+ },
+);
+
+/**
+ * -------------------------------------
+ * EC2 Instance - end
+ */
+
+/**
+ * Application Load Balancer - start
+ * -------------------------------------
+ */
+
+const evidentlyUi_targetGroup = new aws.alb.TargetGroup(
+ "evidentlyUi",
+ {
+ name: "EvidentlyUi",
+ vpcId: evidentlyUi_instanceSubnet_output.vpcId,
+ targetType: "instance",
+ port: 8000,
+ protocol: "HTTP",
+ protocolVersion: "HTTP1",
+ },
+);
+new aws.lb.TargetGroupAttachment(
+ "evidentlyUi",
+ {
+ targetGroupArn: evidentlyUi_targetGroup.arn,
+ targetId: evidentlyUi_instance.id,
+ },
+);
+
+const evidentlyUi_applicationLoadBalancer = new aws.alb.LoadBalancer(
+ "evidentlyUi",
+ {
+ name: "EvidentlyUi",
+ ipAddressType: "ipv4",
+ subnets: [
+ evidentlyUi_publicSubnet_output.id, // external
+ evidentlyUi_instanceSubnet_output.id, // internal
+ ],
+ securityGroups: [
+ evidentlyUi_securityGroup_external.id,
+ evidentlyUi_securityGroup_internal.id,
+ ],
+ accessLogs: { bucket: "" },
+ },
+);
+new aws.alb.Listener(
+ "evidentlyUi-http2https",
+ {
+ loadBalancerArn: evidentlyUi_applicationLoadBalancer.arn,
+ port: 80,
+ defaultActions: [{
+ order: 1,
+ redirect: {
+ port: "443",
+ protocol: "HTTPS",
+ statusCode: "HTTP_301",
+ },
+ type: "redirect",
+ }],
+ },
+);
+new aws.alb.Listener(
+ "evidentlyUi-https",
+ {
+ loadBalancerArn: evidentlyUi_applicationLoadBalancer.arn,
+ port: 443,
+ protocol: "HTTPS",
+ certificateArn: "arn:aws:acm:eu-west-1:012345678901:certificate/01234567-abcd-8901-abcd-abcdef012345",
+ defaultActions: [{
+ order: 1,
+ targetGroupArn: evidentlyUi_targetGroup.arn,
+ type: "forward",
+ }],
+ },
+);
+new aws.route53.Record(
+ "evidentlyUi",
+ {
+ aliases: [{
+ evaluateTargetHealth: true,
+ name: pulumi.interpolate`dualstack.${evidentlyUi_applicationLoadBalancer.dnsName}`,
+ zoneId: "Z012345678ABCD",
+ }],
+ name: "evidently-ui.dev.company.com",
+ type: "A",
+ zoneId: "Z9ABCD12345678",
+ },
+);
+
+/**
+ * -------------------------------------
+ * Application Load Balancer - end
+ */
diff --git a/examples/pulumi/aws/ec2 instance/package.json b/examples/pulumi/aws/evidently-ui on ec2 instance via alb/package.json
similarity index 76%
rename from examples/pulumi/aws/ec2 instance/package.json
rename to examples/pulumi/aws/evidently-ui on ec2 instance via alb/package.json
index 85eff6e..53617f3 100644
--- a/examples/pulumi/aws/ec2 instance/package.json
+++ b/examples/pulumi/aws/evidently-ui on ec2 instance via alb/package.json
@@ -1,5 +1,5 @@
{
- "name": "ec2-instance",
+ "name": "evidently-ui-on-ec2-via-alb",
"main": "index.ts",
"devDependencies": {
"@types/node": "^18",
@@ -8,6 +8,6 @@
"dependencies": {
"@pulumi/aws": "^6.0.0",
"@pulumi/cloudinit": "^1.0.0",
- "yaml": "^2.0.0"
+ "fs": "^0.0.0"
}
-}
\ No newline at end of file
+}
diff --git a/examples/pulumi/aws/ec2 instance/tsconfig.json b/examples/pulumi/aws/evidently-ui on ec2 instance via alb/tsconfig.json
similarity index 100%
rename from examples/pulumi/aws/ec2 instance/tsconfig.json
rename to examples/pulumi/aws/evidently-ui on ec2 instance via alb/tsconfig.json
diff --git a/examples/pulumi/multi-part cloud-init/index.ts b/examples/pulumi/multi-part cloud-init/index.ts
index 67099c4..5485e7f 100644
--- a/examples/pulumi/multi-part cloud-init/index.ts
+++ b/examples/pulumi/multi-part cloud-init/index.ts
@@ -1,5 +1,6 @@
import * as cloudinit from "@pulumi/cloudinit";
import * as fs from 'fs';
+import * as yaml from 'yaml';
export const userData = new cloudinit.Config(
"userData",
@@ -18,6 +19,22 @@ export const userData = new cloudinit.Config(
filename: "cloud-config.docker.yml",
mergeType: "dict(recurse_array,no_replace)+list(append)",
},
+ {
+ contentType: "text/cloud-config",
+ content: yaml.stringify({
+ write_files: [{
+ path: "/etc/cron.daily/security-updates",
+ permissions: "0755",
+ content: [
+ "#!/bin/bash",
+ "dnf -y upgrade --security --nobest",
+ ].join("\n"),
+ defer: true,
+ }],
+ }),
+ filename: "cloud-config.security-updates.yml",
+ mergeType: "dict(recurse_array,no_replace)+list(append)",
+ },
],
},
);
diff --git a/examples/pulumi/multi-part cloud-init/package.json b/examples/pulumi/multi-part cloud-init/package.json
index ff86adb..7a86cb0 100644
--- a/examples/pulumi/multi-part cloud-init/package.json
+++ b/examples/pulumi/multi-part cloud-init/package.json
@@ -2,10 +2,11 @@
"name": "cloud-init.multi-part",
"main": "index.ts",
"devDependencies": {
- "@types/node": "^18"
+ "@types/node": "^18",
+ "typescript": "^5.0.0"
},
"dependencies": {
- "@pulumi/cloudinit": "^1.4.1",
- "typescript": "^5.0.0"
+ "@pulumi/cloudinit": "^1.4.6",
+ "yaml": "^2.5.1"
}
-}
\ No newline at end of file
+}
diff --git a/knowledge base/evidently.md b/knowledge base/evidently.md
new file mode 100644
index 0000000..c75d995
--- /dev/null
+++ b/knowledge base/evidently.md
@@ -0,0 +1,97 @@
+# Evidently
+
+AI observability tool written in [Python].
+
+1. [TL;DR](#tldr)
+1. [ML monitoring dashboard](#ml-monitoring-dashboard)
+ 1. [Remote snapshot storage](#remote-snapshot-storage)
+1. [Collector](#collector)
+1. [Further readings](#further-readings)
+ 1. [Sources](#sources)
+
+## TL;DR
+
+
+ Setup
+
+```sh
+pip install 'evidently'
+pip install 'evidently[llm]' 's3fs' 'tracely'
+```
+
+
+
+
+ Usage
+
+```sh
+evidently ui
+evidently ui … --host='0.0.0.0' --port='8080'
+FSSPEC_S3_KEY='AKIA2HKHF74L0123ABCD' FSSPEC_S3_SECRET='jlc/m1sO…' evidently ui … --workspace='s3://bucket/prefix'
+
+evidently collector
+```
+
+
+
+## ML monitoring dashboard
+
+Visualizes ML system performance over time and allows for issues detection.
+
+Available as cloud service or self-hosted.
+Evidently Cloud offers extra features (e.g. user authentication and roles, built-in alerting, no-code interface).
+
+### Remote snapshot storage
+
+One can store snapshots in a remote data store such as S3 buckets.
+The Monitoring UI service will interface with it to read the snapshots' data.
+
+Evidently connects to data stores using [`fsspec`][fsspec].
+It allows accessing data on remote file systems via standard Python interfaces
+([built-in implementations][fsspec built-in implementations], [other implementations][fsspec other implementations]).
+
+```sh
+pip install 'evidently[llm]' 's3fs'
+evidently ui --host='0.0.0.0' --port='8000' --workspace='s3://bucket/prefix'
+```
+
+## Collector
+
+```sh
+evidently collector
+```
+
+## Further readings
+
+- [Website]
+- [Main repository]
+- [Docker image]
+- [Python]
+- [`fsspec`][fsspec]
+- [ML observability course]
+
+### Sources
+
+- [Documentation]
+
+
+
+
+
+[python]: python.md
+
+
+
+[docker image]: https://hub.docker.com/r/evidently/evidently-service
+[documentation]: https://docs.evidentlyai.com/
+[main repository]: https://github.com/evidentlyai/evidently
+[ml observability course]: https://learn.evidentlyai.com/
+[website]: https://www.evidentlyai.com/
+
+
+[fsspec built-in implementations]: https://filesystem-spec.readthedocs.io/en/latest/api.html#built-in-implementations
+[fsspec other implementations]: https://filesystem-spec.readthedocs.io/en/latest/api.html#other-known-implementations
+[fsspec]: https://filesystem-spec.readthedocs.io/en/latest/
diff --git a/knowledge base/pip.md b/knowledge base/pip.md
index cd68393..6ec0c38 100644
--- a/knowledge base/pip.md
+++ b/knowledge base/pip.md
@@ -8,6 +8,25 @@ Package installer for Python.
## TL;DR
+Stores the cache in:
+
+- `$XDG_CACHE_HOME` (default: `~/.cache/pip`) on Linux.
+- `~/Library/Caches/pip` on Mac OS X.
+- `%LocalAppData%\pip\Cache` on Windows.
+
+pip will also respect XDG_CACHE_HOME.
+
+Creates **temporary** files to unpack/build/doOtherStuff to packages, then deletes them after installation.
+It checks, in order, if any of the directories used by `tempfile.gettempdir()` **exists**, and is **readable** and
+**writable**; the first one matching all the requirements is used.
+The directory priority at the time of writing is as follows:
+
+1. `$TMPDIR`
+1. `$TEMP`
+1. `$TMP`
+1. `C:\TEMP`, `C:\TMP`, `\TEMP`, and `\TMP` on Windows; `/tmp`, `/var/tmp`, and `/usr/tmp` on any other platform.
+1. The current working directory
+
```sh
# Install packages.
pip install 'yamllint'
@@ -26,6 +45,23 @@ pip install --requirement <(pip freeze | sed 's/==/>=/') --upgrade
# Generate a list of the outdated packages.
pip list --outdated
+# Get the currently configured cache directory.
+pip cache dir
+
+# Provide an overview of the contents of the cache.
+pip cache info
+
+# List files from the 'wheel' cache.
+pip cache list
+pip cache list 'ansible'
+
+# Removes files from the 'wheel' cache.
+# Files from the 'HTTP' cache are left untouched at this time.
+pip cache remove 'setuptools'
+
+# Clear all files from the 'wheel' and 'HTTP' caches.
+pip cache purge
+
# Remove orphaned dependencies.
# Requires `pip-autoremove`.
pip-autoremove
diff --git a/knowledge base/python.md b/knowledge base/python.md
index 2605459..3eb00e5 100644
--- a/knowledge base/python.md
+++ b/knowledge base/python.md
@@ -1,7 +1,5 @@
# Python
-## Table of contents
-
1. [TL;DR](#tldr)
1. [Dictionaries](#dictionaries)
1. [F-strings](#f-strings)
@@ -235,7 +233,8 @@ All the references in the [further readings] section, plus the following:
- [Click]
diff --git a/snippets/aws/commands.fish b/snippets/aws/commands.fish
index 8ace678..4bd2efc 100644
--- a/snippets/aws/commands.fish
+++ b/snippets/aws/commands.fish
@@ -122,6 +122,13 @@ aws ec2 describe-instances --output 'text' \
watch -n '1' aws ec2 describe-instances --instance-ids 'i-0123456789abcdef0' --query 'Reservations[].Instances[].[State,StateTransitionReason]'
+# Retrieve the security credentials for an IAM role named 's3access'
+# IMDSv2
+TOKEN=$(curl -X PUT 'http://169.254.169.254/latest/api/token' -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600') \
+&& curl -H "X-aws-ec2-metadata-token: ${TOKEN}" 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access'
+# IMDSv1
+curl 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access'
+
###
# ECR
diff --git a/snippets/pip.sh b/snippets/pip.sh
new file mode 100644
index 0000000..08d692f
--- /dev/null
+++ b/snippets/pip.sh
@@ -0,0 +1,35 @@
+#!/usr/bin/env sh
+
+# Install packages
+pip install 'yamllint'
+pip install --user 'ansible==10.1.0'
+pip install -U --require-virtualenv -r 'requirements.txt' --no-cache-dir
+
+# Upgrade packages
+pip install -U 'pip'
+
+# Upgrade the included `pip` executable on Mac OS X
+~/Library/Python/3.8/bin/pip3 install --user --upgrade 'pip'
+
+# Upgrade all currently installed packages
+pip install --requirement <(pip freeze | sed 's/==/>=/') --upgrade
+
+# Generate a list of the outdated packages
+pip list --outdated
+
+# Get the currently configured cache directory
+pip cache dir
+
+# Provide an overview of the contents of the cache
+pip cache info
+
+# List files from the 'wheel' cache
+pip cache list
+pip cache list 'ansible'
+
+# Removes files from the 'wheel' cache
+# Files from the 'HTTP' cache are left untouched at this time
+pip cache remove 'setuptools'
+
+# Clear all files from the 'wheel' and 'HTTP' caches
+pip cache purge
diff --git a/snippets/pulumi/aws create rds instance from latest snapshot.ts b/snippets/pulumi/aws/create rds instance from latest snapshot.ts
similarity index 100%
rename from snippets/pulumi/aws create rds instance from latest snapshot.ts
rename to snippets/pulumi/aws/create rds instance from latest snapshot.ts
diff --git a/snippets/pulumi/aws/get existing resources information.ts b/snippets/pulumi/aws/get existing resources information.ts
new file mode 100644
index 0000000..cf96ab8
--- /dev/null
+++ b/snippets/pulumi/aws/get existing resources information.ts
@@ -0,0 +1,63 @@
+import * as aws from "@pulumi/aws";
+import * as pulumi from "@pulumi/pulumi";
+
+const ec2Ami_amazonLinux2023_arm64_available_latest_output: pulumi.Output = aws.ec2.getAmiOutput({
+ owners: [ "amazon", ],
+ nameRegex: "^al2023-ami-2023.*",
+ filters: [
+ {
+ name: "architecture",
+ values: [ "arm64" ],
+ },
+ {
+ name: "state",
+ values: [ "available" ],
+ },
+ ],
+ mostRecent: true,
+});
+const ec2KeyPair_output: pulumi.Output = aws.ec2.getKeyPairOutput({ keyName: "john-ec2KeyPair" });
+const ec2Subnet: pulumi.Output = aws.ec2.getSubnetOutput({
+ filters: [{
+ name: "tag:Name",
+ values: [ "Private Subnet in AZ C" ],
+ }],
+});
+pulumi.all([
+ ec2Ami_amazonLinux2023_arm64_available_latest_output,
+ ec2KeyPair_output,
+ ec2Subnet,
+]).apply( ([ ami, keyPair, subnet ]) => console.log(`${ami.arn}, ${keyPair.arn}, ${subnet.arn}`) );
+
+
+const s3bucket_output = aws.s3.getBucketOutput({ bucket: "some-bucket" });
+s3bucket_output.arn.apply(
+ (bucketArn: aws.ARN) => new aws.iam.Role(
+ "bucket",
+ {
+ name: "BucketInstanceRole",
+ assumeRolePolicy: JSON.stringify({
+ Version: "2012-10-17",
+ Statement: [{
+ Effect: "Allow",
+ Principal: { Service: "ec2.amazonaws.com" },
+ Action: "sts:AssumeRole",
+ }],
+ }),
+ inlinePolicies: [{
+ name: "AllowManagingOwnBucket",
+ policy: JSON.stringify({
+ Version: "2012-10-17",
+ Statement: [{
+ Effect: "Allow",
+ Action: "s3:*",
+ Resource: [
+ `${bucketArn}`,
+ `${bucketArn}/*`,
+ ],
+ }],
+ }),
+ }],
+ },
+ ),
+);
diff --git a/snippets/pulumi/aws iam groups generation.ts b/snippets/pulumi/aws/iam groups generation.ts
similarity index 100%
rename from snippets/pulumi/aws iam groups generation.ts
rename to snippets/pulumi/aws/iam groups generation.ts
diff --git a/snippets/pulumi/aws rds s3 exporter iam role.ts b/snippets/pulumi/aws/rds s3 exporter iam role.ts
similarity index 100%
rename from snippets/pulumi/aws rds s3 exporter iam role.ts
rename to snippets/pulumi/aws/rds s3 exporter iam role.ts