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