├── Chapter11 ├── Emoji.ipynb ├── concat_json.py ├── parse.py └── parse_bad.py ├── Chapter13 └── PingPong.json ├── Chapter2 ├── docker_pull.py └── ec2-start-stp.py ├── Chapter3 ├── HuggingFaceTest.ipynb ├── Networking.ipynb ├── main.py └── netiface_test.py ├── Chapter4 ├── autoscale_create.py ├── create_ec2.py ├── docker_sample.py ├── kubernetes_sample.py ├── stop_ec2.py └── update_ec2.py ├── Chapter5 ├── ab_testing.py ├── edge_testing.py ├── feature_flags.py ├── marshal_example.py └── multiprocessing_example.py ├── Chapter6 ├── PII.py ├── attestor.py ├── cpu_util.ipynb └── update_cluster.py ├── Chapter7 ├── azure_kubernetes.py ├── call_lambda.gs ├── create_lambda_ec2.py ├── fleet_maintenance.py ├── gcp_kubernetes.py ├── os_patching.py └── required_containers.py ├── Chapter8 ├── consumer.py ├── image_resizer.py └── producer.py ├── Chapter9 ├── concatenate_strings.py ├── rollback.py └── todoist.py ├── LICENSE └── README.md /Chapter11/Emoji.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [] 7 | }, 8 | "kernelspec": { 9 | "name": "python3", 10 | "display_name": "Python 3" 11 | }, 12 | "language_info": { 13 | "name": "python" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "metadata": { 21 | "id": "9BkhUmnRYibB" 22 | }, 23 | "outputs": [], 24 | "source": [ 25 | "user_data = {\n", 26 | " 'username': 'user_with_emoji😊',\n", 27 | "}" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "source": [], 33 | "metadata": { 34 | "id": "AMRL8K_efh9e" 35 | }, 36 | "execution_count": null, 37 | "outputs": [] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "source": [ 42 | "import json\n", 43 | "\n", 44 | "with open('sample.json', 'w', encoding='utf-8') as file:\n", 45 | " json.dump(user_data, file, ensure_ascii=False, indent=2)" 46 | ], 47 | "metadata": { 48 | "id": "s3gt6mYMY61W" 49 | }, 50 | "execution_count": null, 51 | "outputs": [] 52 | } 53 | ] 54 | } -------------------------------------------------------------------------------- /Chapter11/concat_json.py: -------------------------------------------------------------------------------- 1 | a = {"one":1, "two":2} 2 | b = {"one":"one", "two":2, "three":3} 3 | 4 | print(a|b) 5 | -------------------------------------------------------------------------------- /Chapter11/parse.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | def read_large_csv(file_path): 4 | with open(file_path, 'r') as csv_file: 5 | csv_reader = csv.reader(csv_file) 6 | 7 | # Skip header if present 8 | next(csv_reader, None) 9 | 10 | for row in csv_reader: 11 | yield row 12 | 13 | # Example usage 14 | csv_file_path = 'MOCK_DATA.csv' 15 | for row in read_large_csv(csv_file_path): 16 | # Process each row as needed 17 | print(row) 18 | -------------------------------------------------------------------------------- /Chapter11/parse_bad.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | with open('MOCK_DATA.csv', 'r') as csv_file: 4 | csv_reader = csv.reader(csv_file) 5 | 6 | # Skip header if present 7 | next(csv_reader, None) 8 | 9 | for row in csv_reader: 10 | print(row) 11 | -------------------------------------------------------------------------------- /Chapter13/PingPong.json: -------------------------------------------------------------------------------- 1 | { 2 | "Comment": "A description of my state machine", 3 | "StartAt": "Parallel", 4 | "States": { 5 | "Parallel": { 6 | "Type": "Parallel", 7 | "Branches": [ 8 | { 9 | "StartAt": "Ping", 10 | "States": { 11 | "Ping": { 12 | "Type": "Pass", 13 | "Parameters": { 14 | "ping.$": "States.MathRandom($.start, $.end)", 15 | "start.$": "$.start", 16 | "end.$": "$.end" 17 | }, 18 | "End": true 19 | } 20 | } 21 | }, 22 | { 23 | "StartAt": "Pong", 24 | "States": { 25 | "Pong": { 26 | "Type": "Pass", 27 | "Parameters": { 28 | "pong.$": "States.MathRandom($.start, $.end)" 29 | }, 30 | "End": true 31 | } 32 | } 33 | } 34 | ], 35 | "Next": "Choice" 36 | }, 37 | "Choice": { 38 | "Type": "Choice", 39 | "Choices": [ 40 | { 41 | "Variable": "$[0].ping", 42 | "NumericEqualsPath": "$[1].pong", 43 | "Next": "Success" 44 | } 45 | ], 46 | "Default": "Pass" 47 | }, 48 | "Pass": { 49 | "Type": "Pass", 50 | "Next": "Parallel", 51 | "Parameters": { 52 | "start.$": "$[0].start", 53 | "end.$": "$[0].end" 54 | } 55 | }, 56 | "Success": { 57 | "Type": "Succeed" 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Chapter2/docker_pull.py: -------------------------------------------------------------------------------- 1 | import docker 2 | 3 | def pull_docker_images(): 4 | client = docker.from_env() 5 | image_list = ["redis:latest", "nginx:latest"] 6 | for image in image_list: 7 | print("Pulling image {}".format(image)) 8 | client.images.pull(image) 9 | 10 | if __name__ == "__main__": 11 | pull_docker_images() 12 | -------------------------------------------------------------------------------- /Chapter2/ec2-start-stp.py: -------------------------------------------------------------------------------- 1 | import boto3 2 | import datetime 3 | 4 | ec2_client = boto3.client('ec2') 5 | 6 | def lambda_handler(event, context): 7 | current_time = datetime.datetime.now().strftime("%H:%M:%S") 8 | print(f"Current time is: {current_time}") 9 | instance_id = 'i-07e253eb7f6f0aeed' 10 | 11 | if current_time >= '00:00:00' and current_time <= '03:59:59': 12 | print("Starting EC2 instance...") 13 | response = ec2_client.start_instances(InstanceIds=[instance_id]) 14 | print(f"EC2 instance {instance_id} started.") 15 | elif current_time >= '04:00:00' and current_time <= '23:59:59': 16 | print("Stopping EC2 instance...") 17 | response = ec2_client.stop_instances(InstanceIds=[instance_id]) 18 | print(f"EC2 instance {instance_id} stopped.") 19 | else: 20 | print("Not within the scheduled time window.") 21 | -------------------------------------------------------------------------------- /Chapter3/HuggingFaceTest.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [], 7 | "gpuType": "T4" 8 | }, 9 | "kernelspec": { 10 | "name": "python3", 11 | "display_name": "Python 3" 12 | }, 13 | "language_info": { 14 | "name": "python" 15 | }, 16 | "accelerator": "GPU" 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "code", 21 | "execution_count": null, 22 | "metadata": { 23 | "id": "mwXUcr7wBZbj" 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "!pip install huggingface_hub transformers[agents]" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "source": [ 33 | "from huggingface_hub import login\n", 34 | "\n", 35 | "login(\"\")" 36 | ], 37 | "metadata": { 38 | "id": "z48Rgtz6IcAF" 39 | }, 40 | "execution_count": null, 41 | "outputs": [] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "source": [ 46 | "from transformers import HfAgent\n", 47 | "\n", 48 | "agent = HfAgent(\"https://api-inference.huggingface.co/models/bigcode/starcoderbase\")" 49 | ], 50 | "metadata": { 51 | "id": "VMppsQluJG7b" 52 | }, 53 | "execution_count": null, 54 | "outputs": [] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "source": [ 59 | "agent.run(\"Draw me a picture of `prompt`\", prompt=\"rainbow butterflies\")" 60 | ], 61 | "metadata": { 62 | "id": "4BuzW4cHORYR" 63 | }, 64 | "execution_count": null, 65 | "outputs": [] 66 | } 67 | ] 68 | } -------------------------------------------------------------------------------- /Chapter3/Networking.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": { 7 | "id": "AXROaNNEtx0g" 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "!pip install scapy matplotlib" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": null, 17 | "metadata": { 18 | "id": "wT2owBsLt5ek" 19 | }, 20 | "outputs": [], 21 | "source": [ 22 | "from scapy.all import IP, ICMP, sr, traceroute\n", 23 | "\n", 24 | "# Define the target host\n", 25 | "target_host = [\"bing.com\", \"google.com\", \"duckduckgo.com\"]\n", 26 | "\n", 27 | "# Perform the traceroute\n", 28 | "result, _ = traceroute(target_host, maxttl=5)\n", 29 | "\n", 30 | "# Display the results\n", 31 | "result.show()\n" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": null, 37 | "metadata": { 38 | "id": "RX8taOgugq_M" 39 | }, 40 | "outputs": [], 41 | "source": [ 42 | "from scapy.all import sniff\n", 43 | "\n", 44 | "# Lists to store packet sizes and timestamps\n", 45 | "packet_sizes = []\n", 46 | "timestamps = []\n", 47 | "\n", 48 | "#Handle packets and get the necessary data\n", 49 | "def packet_handler(packet):\n", 50 | " print(packet)\n", 51 | " packet_sizes.append(len(packet))\n", 52 | " timestamps.append(packet.time)\n", 53 | "\n", 54 | "# Start packet sniffing on the default network interface\n", 55 | "sniff(prn=packet_handler, count=100)" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "source": [ 61 | "import matplotlib.pyplot as plt\n", 62 | "\n", 63 | "# Create a plot\n", 64 | "plt.figure(figsize=(16, 8))\n", 65 | "plt.plot(timestamps, packet_sizes, marker='o')\n", 66 | "plt.xlabel(\"Time\")\n", 67 | "plt.ylabel(\"Packet Size\")\n", 68 | "plt.title(\"Packet Size over Time\")\n", 69 | "plt.grid(True)\n", 70 | "plt.show()" 71 | ], 72 | "metadata": { 73 | "id": "WEUyMfhFUJxQ" 74 | }, 75 | "execution_count": null, 76 | "outputs": [] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "source": [ 81 | "from scapy.all import sniff\n", 82 | "from scapy.layers.inet import IP\n", 83 | "import matplotlib.pyplot as plt\n", 84 | "\n", 85 | "# Lists to store packet sizes and timestamps\n", 86 | "packet_sizes = []\n", 87 | "timestamps = []\n", 88 | "\n", 89 | "def packet_handler(packet):\n", 90 | " print(packet)\n", 91 | " packet_sizes.append(len(packet))\n", 92 | " timestamps.append(packet.time)\n", 93 | "\n", 94 | "# Start packet sniffing on the default network interface\n", 95 | "sniff(prn=packet_handler, filter=\"ip\", count=100)\n", 96 | "\n", 97 | "# Create a plot\n", 98 | "plt.figure(figsize=(16, 8))\n", 99 | "plt.plot(timestamps, packet_sizes, marker='o')\n", 100 | "plt.xlabel(\"Time\")\n", 101 | "plt.ylabel(\"Packet Size\")\n", 102 | "plt.title(\"Packet Size over Time\")\n", 103 | "plt.grid(True)\n", 104 | "plt.show()\n" 105 | ], 106 | "metadata": { 107 | "id": "kQIJfuJE2Wjd" 108 | }, 109 | "execution_count": null, 110 | "outputs": [] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "source": [ 115 | "!pip install netifaces" 116 | ], 117 | "metadata": { 118 | "id": "fj9QwdCZXewJ" 119 | }, 120 | "execution_count": null, 121 | "outputs": [] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "source": [ 126 | "import netifaces\n", 127 | "\n", 128 | "def generate_routing_table():\n", 129 | " routing_table = []\n", 130 | " for interface in netifaces.interfaces():\n", 131 | " addresses = netifaces.ifaddresses(interface)\n", 132 | " if netifaces.AF_INET in addresses:\n", 133 | " for entry in addresses[netifaces.AF_INET]:\n", 134 | " if 'netmask' in entry and 'addr' in entry:\n", 135 | " routing_entry = {\n", 136 | " 'interface': interface,\n", 137 | " 'destination': entry['addr'],\n", 138 | " 'netmask': entry['netmask']\n", 139 | " }\n", 140 | " routing_table.append(routing_entry)\n", 141 | " return routing_table\n", 142 | "\n", 143 | "routing_table = generate_routing_table()\n", 144 | "for entry in routing_table:\n", 145 | " print(f\"Interface: {entry['interface']}\")\n", 146 | " print(f\"Destination: {entry['destination']}\")\n", 147 | " print(f\"Netmask: {entry['netmask']}\")\n", 148 | " print(\"-\" * 30)\n" 149 | ], 150 | "metadata": { 151 | "id": "hir370m3XjVE" 152 | }, 153 | "execution_count": null, 154 | "outputs": [] 155 | } 156 | ], 157 | "metadata": { 158 | "colab": { 159 | "provenance": [] 160 | }, 161 | "kernelspec": { 162 | "display_name": "Python 3", 163 | "name": "python3" 164 | }, 165 | "language_info": { 166 | "name": "python" 167 | } 168 | }, 169 | "nbformat": 4, 170 | "nbformat_minor": 0 171 | } -------------------------------------------------------------------------------- /Chapter3/main.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request 2 | 3 | app = Flask(__name__) 4 | 5 | 6 | @app.route('/') 7 | def index(): 8 | num1 = request.args.get("num1") 9 | num2 = request.args.get("num2") 10 | returning_json_value = {"Sum of parameters":int(num1) + int(num2)} 11 | return returning_json_value 12 | 13 | 14 | app.run(host='0.0.0.0', port=81) 15 | -------------------------------------------------------------------------------- /Chapter3/netiface_test.py: -------------------------------------------------------------------------------- 1 | import netifaces 2 | 3 | def generate_routing_table(): 4 | routing_table = [] 5 | for interface in netifaces.interfaces(): 6 | addresses = netifaces.ifaddresses(interface) 7 | if netifaces.AF_INET in addresses: 8 | for entry in addresses[netifaces.AF_INET]: 9 | if 'netmask' in entry and 'addr' in entry: 10 | routing_entry = { 11 | 'interface': interface, 12 | 'destination': entry['addr'], 13 | 'netmask': entry['netmask'] 14 | } 15 | routing_table.append(routing_entry) 16 | return routing_table 17 | 18 | if __name__ == "__main__": 19 | routing_table = generate_routing_table() 20 | for entry in routing_table: 21 | print(f"Interface: {entry['interface']}") 22 | print(f"Destination: {entry['destination']}") 23 | print(f"Netmask: {entry['netmask']}") 24 | print("-" * 30) 25 | -------------------------------------------------------------------------------- /Chapter4/autoscale_create.py: -------------------------------------------------------------------------------- 1 | import boto3 2 | 3 | def autoscale_create(): 4 | autoscaling = boto3.client('autoscaling') 5 | 6 | #create a launch configuration for use in autoscaling 7 | # autoscaling.create_launch_configuration( 8 | # LaunchConfigurationName="book_configuration", 9 | # ImageId="ami-051f7e7f6c2f40dc1", 10 | # InstanceType="t2.micro", 11 | # ) 12 | 13 | # #create an autoscaling group with your launch configuration 14 | # autoscaling.create_auto_scaling_group( 15 | # AutoScalingGroupName="book_autoscaler", 16 | # LaunchConfigurationName="book_configuration", 17 | # MinSize=2, 18 | # MaxSize=5, 19 | # DesiredCapacity=2, 20 | # AvailabilityZones=['us-east-1a', 'us-east-1b'], 21 | # ) 22 | 23 | # #create a policy for your autoscaling group 24 | # autoscaling.put_scaling_policy( 25 | # AutoScalingGroupName="book_autoscaler", 26 | # PolicyName="book_scale", 27 | # PolicyType='TargetTrackingScaling', 28 | # TargetTrackingConfiguration={ 29 | # 'PredefinedMetricSpecification': { 30 | # 'PredefinedMetricType': 'ASGAverageCPUUtilization' 31 | # }, 32 | # 'TargetValue': 70 33 | # } 34 | # ) 35 | 36 | #update policy to 80 percent 37 | autoscaling.put_scaling_policy( 38 | AutoScalingGroupName="book_autoscaler", 39 | PolicyName="book_scale", 40 | PolicyType='TargetTrackingScaling', 41 | TargetTrackingConfiguration={ 42 | 'PredefinedMetricSpecification': { 43 | 'PredefinedMetricType': 'ASGAverageCPUUtilization' 44 | }, 45 | 'TargetValue': 80 46 | } 47 | ) 48 | 49 | if __name__ == "__main__": 50 | autoscale_create() -------------------------------------------------------------------------------- /Chapter4/create_ec2.py: -------------------------------------------------------------------------------- 1 | import boto3 2 | 3 | def create_ec2(): 4 | ec2_client = boto3.resource("ec2") 5 | print(ec2_client.create_instances(ImageId="ami-051f7e7f6c2f40dc1", 6 | InstanceType="t2.nano", MaxCount=1, MinCount=1)) 7 | 8 | if __name__ == "__main__": 9 | create_ec2() -------------------------------------------------------------------------------- /Chapter4/docker_sample.py: -------------------------------------------------------------------------------- 1 | import docker 2 | 3 | def docker_sample(): 4 | client = docker.from_env() 5 | 6 | # Define the image name and tag 7 | image_name = 'python:latest' 8 | 9 | # Pull the image 10 | client.images.pull(image_name) 11 | 12 | # Create and run a container based on the pulled image 13 | container = client.containers.create(image_name) 14 | container.start() 15 | print(client.containers.list()) 16 | 17 | if __name__ == "__main__": 18 | docker_sample() -------------------------------------------------------------------------------- /Chapter4/kubernetes_sample.py: -------------------------------------------------------------------------------- 1 | from kubernetes import client, config 2 | 3 | # Load Kubernetes configurations 4 | config.load_kube_config() 5 | 6 | # Create a Kubernetes client 7 | api = client.CoreV1Api() 8 | 9 | # Define namespaces 10 | namespaces = ['mynamespace1', 'mynamespace2'] 11 | 12 | # Create namespaces 13 | for namespace in namespaces: 14 | namespace_client = client.V1Namespace(metadata=client.V1ObjectMeta(name=namespace)) 15 | api.create_namespace(namespace_client) 16 | 17 | # Create a Kubernetes networking V1 API client 18 | networking_api = client.NetworkingV1Api() 19 | 20 | for namespace in namespaces: 21 | # Define the Network Policy manifest 22 | network_policy_manifest = { 23 | "apiVersion": "networking.k8s.io/v1", 24 | "kind": "NetworkPolicy", 25 | "metadata": { 26 | "name": "block-external-traffic", 27 | "namespace": namespace 28 | }, 29 | "spec": { 30 | "podSelector": {}, 31 | "policyTypes": ["Ingress"] 32 | } 33 | } 34 | 35 | # Create the Network Policy 36 | networking_api.create_namespaced_network_policy(namespace=namespace, 37 | body=network_policy_manifest) 38 | -------------------------------------------------------------------------------- /Chapter4/stop_ec2.py: -------------------------------------------------------------------------------- 1 | import boto3 2 | 3 | def stop_ec2(): 4 | ec2_client = boto3.client("ec2") 5 | print(ec2_client.stop_instances(InstanceIds=["i-02d42ec52027baa08"])) 6 | 7 | if __name__ == "__main__": 8 | stop_ec2() -------------------------------------------------------------------------------- /Chapter4/update_ec2.py: -------------------------------------------------------------------------------- 1 | import boto3 2 | 3 | def update_ec2(): 4 | ec2_client = boto3.client("ec2") 5 | print(ec2_client.modify_instance_attribute( 6 | InstanceId="i-02d42ec52027baa08", 7 | InstanceType={ 8 | 'Value': 't2.micro', 9 | } 10 | )) 11 | 12 | if __name__ == "__main__": 13 | update_ec2() -------------------------------------------------------------------------------- /Chapter5/ab_testing.py: -------------------------------------------------------------------------------- 1 | ''' get request from user ''' 2 | def process_request(request): 3 | ''' get a random number between 1 and 10 ''' 4 | num = random.randrange(1,10) 5 | ''' conditionally return site containing special feature ''' 6 | if num<=2: 7 | return special_response(request) 8 | else: 9 | return regular_response(request) 10 | -------------------------------------------------------------------------------- /Chapter5/edge_testing.py: -------------------------------------------------------------------------------- 1 | ''' the request variable is a json that contains the request headers 2 | and body''' 3 | def process_request(request): 4 | '''get all headers''' 5 | headers = request["headers"] 6 | ''' we're using country in this example, but this is any arbitrary 7 | header you choose to pass ''' 8 | request_country = headers["country"] 9 | ''' throw to a function that maps each available server to a country 10 | ''' 11 | server = server_map(request_country) 12 | ''' return value from correct server as prescribed by server map ''' 13 | return server_response(server, request) 14 | -------------------------------------------------------------------------------- /Chapter5/feature_flags.py: -------------------------------------------------------------------------------- 1 | ''' get request from user ''' 2 | def process_request(request): 3 | '''get request header with feature flag ''' 4 | header = request["header"] 5 | feature = header["feature"] 6 | ''' Check if feature flag is turned on, i.e. if it is True or False 7 | ''' 8 | if feature: 9 | return featured_response(request) 10 | else: 11 | return normal_response(request) 12 | -------------------------------------------------------------------------------- /Chapter5/marshal_example.py: -------------------------------------------------------------------------------- 1 | import marshal 2 | ''' function to decode bytes ''' 3 | def decode_bytes(data): 4 | ''' Load binary data into readable data with marshal ''' 5 | result = marshal.loads(data) 6 | ''' Return raw data ''' 7 | return result 8 | -------------------------------------------------------------------------------- /Chapter5/multiprocessing_example.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | ''' Get list and return sum ''' 3 | def get_sum(numerical_array): 4 | ''' return sum of array ''' 5 | return sum(numerical_array) 6 | '''method that calls sum method to get total sum for 1 million records 7 | ''' 8 | def get_total_sum(full_array): 9 | ''' Initialize 4 processors ''' 10 | pool = multiprocessing.Pool(processes=4) 11 | ''' List of sums in 10,000 number blocks ''' 12 | sum_list = [] 13 | ''' Get 10,000 values at a time for sum out of 1,000,000 ''' 14 | for i in range(0, count(full_array)/10000): 15 | sum_array = full_array[i*10000:(i+1)*10000] 16 | '''Make an array of 10,000 length arrays ''' 17 | sum_list.append(sum_array) 18 | ''' Get final array of sums of each 10,000 value array ''' 19 | final_array_list = pool.map(get_sum, sum_list) 20 | ''' Get one final sum of all these elements ''' 21 | return sum(final_array_list) 22 | -------------------------------------------------------------------------------- /Chapter6/PII.py: -------------------------------------------------------------------------------- 1 | #initial text 2 | import re 3 | text = "The first number is 901-895-7906. The second number is: 081-548-3262" 4 | #pattern for search 5 | search_pattern = r'\d{3}-\d{3}-\d{4}' 6 | #replacement for pattern 7 | replacement_text = "" 8 | #text replacement 9 | new_text = re.sub(search_pattern, replacement_text, text) 10 | #output given: "The first number is . The second number is: " 11 | print(new_text) 12 | -------------------------------------------------------------------------------- /Chapter6/attestor.py: -------------------------------------------------------------------------------- 1 | from google.cloud import binaryauthorization_v1 2 | def sample_create_attestor(): 3 | client = binaryauthorization_v1.BinauthzManagementServiceV1Client() 4 | attestor = binaryauthorization_v1.Attestor() 5 | attestor.name = 6 | request = binaryauthorization_v1.CreateAttestorRequest( 7 | parent=, 8 | attestor_id=, 9 | attestor=attestor, 10 | ) 11 | client.create_attestor(request=request) 12 | -------------------------------------------------------------------------------- /Chapter6/cpu_util.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [] 7 | }, 8 | "kernelspec": { 9 | "name": "python3", 10 | "display_name": "Python 3" 11 | }, 12 | "language_info": { 13 | "name": "python" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "metadata": { 21 | "id": "GYLjRPQEBRBo" 22 | }, 23 | "outputs": [], 24 | "source": [ 25 | "!pip install pandas matplotlib" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "source": [ 31 | "import pandas as pd\n", 32 | "\n", 33 | "df = pd.read_csv(\"MOCK_DATA.csv\")\n", 34 | "df.sort_values(by=\"timestamp\", inplace=True)\n", 35 | "df" 36 | ], 37 | "metadata": { 38 | "id": "Z3v5jtatBUoU" 39 | }, 40 | "execution_count": null, 41 | "outputs": [] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "source": [ 46 | "import matplotlib.pyplot as plt\n", 47 | "\n", 48 | "plt.figure(figsize=(20, 20))\n", 49 | "plt.plot(df['timestamp'], df['cpu_utilization'], label='Data')\n", 50 | "\n", 51 | "plt.title('Plot for CPU utilization')\n", 52 | "plt.xlabel('Time')\n", 53 | "plt.ylabel('CPU utilization')\n", 54 | "plt.grid(True)\n", 55 | "plt.legend()\n", 56 | "\n", 57 | "plt.show()" 58 | ], 59 | "metadata": { 60 | "id": "z2wq3iLxDPIi" 61 | }, 62 | "execution_count": null, 63 | "outputs": [] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "source": [], 68 | "metadata": { 69 | "id": "hSZlW__ZLtBR" 70 | }, 71 | "execution_count": null, 72 | "outputs": [] 73 | } 74 | ] 75 | } -------------------------------------------------------------------------------- /Chapter6/update_cluster.py: -------------------------------------------------------------------------------- 1 | from google.cloud import container_v1 2 | def sample_update_cluster(): 3 | client = container_v1.ClusterManagerClient() 4 | request = container_v1.UpdateClusterRequest( 5 | "desired_node_pool_id": , 6 | "update": { 7 | "desired_binary_authorization": { 8 | "enabled": True, 9 | "evaluation_mode": 2 10 | } 11 | } 12 | ) 13 | client.update_cluster(request=request) 14 | -------------------------------------------------------------------------------- /Chapter7/azure_kubernetes.py: -------------------------------------------------------------------------------- 1 | from azure.mgmt.containerservice.models import ManagedCluster, ManagedClusterAgentPoolProfile 2 | 3 | resource_group = '' 4 | 5 | cluster_name = '' 6 | 7 | location = '' 8 | 9 | agent_pool_profile = ManagedClusterAgentPoolProfile( 10 | 11 | name='agentpool', 12 | 13 | count=3, 14 | 15 | vm_size='Standard_DS2_v2', 16 | 17 | ) 18 | 19 | aks_cluster = ManagedCluster(location=location, kubernetes_version='1.21.0', agent_pool_profiles = [agent_pool_profile]) 20 | 21 | aks_client.managed_clusters.begin_create_or_update(resource_group, cluster_name, aks_cluster).result() 22 | -------------------------------------------------------------------------------- /Chapter7/call_lambda.gs: -------------------------------------------------------------------------------- 1 | function submitForm(e) { 2 | 3 | var responses = e.values; 4 | 5 | var size = responses[0]; 6 | 7 | var apiUrl = ''; 8 | 9 | var requestData = { 10 | 11 | 'instance_size': size, 12 | 13 | }; 14 | 15 | 16 | 17 | 18 | var requestBody = JSON.stringify(requestData); 19 | 20 | var options = { 21 | 22 | 'method': 'get', 23 | 24 | 'contentType': 'application/json', 25 | 26 | 'payload': requestBody, 27 | 28 | }; 29 | 30 | var response = UrlFetchApp.fetch(apiUrl, options); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /Chapter7/create_lambda_ec2.py: -------------------------------------------------------------------------------- 1 | import boto3 2 | 3 | 4 | 5 | ec2 = boto3.client('ec2') 6 | 7 | 8 | 9 | def lambda_handler(event, context): 10 | 11 | instance_size = event['instance_size'] 12 | 13 | 14 | 15 | response = ec2.run_instances( 16 | 17 | ImageId='', 18 | 19 | InstanceType=instance_size, 20 | 21 | MinCount=1, 22 | 23 | MaxCount=1, 24 | 25 | SecurityGroupIds=[':latest") 30 | 31 | image.save("") 32 | -------------------------------------------------------------------------------- /Chapter8/consumer.py: -------------------------------------------------------------------------------- 1 | from confluent_kafka import Consumer 2 | 3 | 4 | 5 | conf = {'bootstrap.servers': ‘:9092', 6 | 7 | 'group.id': ‘’, 8 | 9 | 'auto.offset.reset': 'smallest'} 10 | 11 | 12 | 13 | consumer = Consumer(conf) 14 | 15 | while True: 16 | 17 | msg = consumer.poll(timeout=1.0) 18 | 19 | if msg is None: continue 20 | 21 | break 22 | -------------------------------------------------------------------------------- /Chapter8/image_resizer.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import tempfile 4 | 5 | import boto3 6 | 7 | from PIL import Image 8 | 9 | 10 | 11 | s3 = boto3.client('s3') 12 | 13 | 14 | 15 | def lambda_handler(event, context): 16 | 17 | # Get the name of the bucket and the image name when upload is triggered. 18 | 19 | bucket = event['Records'][0]['s3']['bucket']['name'] 20 | 21 | key = event['Records'][0]['s3']['object']['key'] 22 | 23 | 24 | 25 | new_width = 300 #width of image 26 | 27 | new_height = 200 #height of image 28 | 29 | 30 | 31 | with tempfile.TemporaryDirectory() as tmpdir: 32 | 33 | # Download the original image from S3 into a pre-defined temporary directory 34 | 35 | download_path = os.path.join(tmpdir, 'original.jpg') 36 | 37 | 38 | 39 | #download the S3 file into the temporay path 40 | 41 | s3.download_file(bucket, key, download_path) 42 | 43 | 44 | 45 | with Image.open(download_path) as image: 46 | 47 | image = image.resize((new_width, new_height)) 48 | 49 | 50 | 51 | # Save the resized image in its own path 52 | 53 | resized_path = os.path.join(tmpdir, 'resized.jpg') 54 | 55 | image.save(resized_path) 56 | 57 | 58 | 59 | # Upload the resized image back to the S3 bucket and delete the original 60 | 61 | s3.delete_object(Bucket=bucket, Key=key) 62 | 63 | s3.upload_file(resized_path, bucket, key) 64 | 65 | 66 | 67 | 68 | 69 | return { 70 | 71 | 'statusCode': 200, 72 | 73 | 'body': 'You don’t really need this because its not for people!' 74 | 75 | } 76 | -------------------------------------------------------------------------------- /Chapter8/producer.py: -------------------------------------------------------------------------------- 1 | from confluent_kafka import Producer 2 | 3 | import socket 4 | 5 | 6 | 7 | conf = {'bootstrap.servers': '‘:9092', 8 | 9 | 'client.id': socket.gethostname()} 10 | 11 | 12 | 13 | producer = Producer(conf) 14 | 15 | producer.produce(topic, key="key", value="value") 16 | -------------------------------------------------------------------------------- /Chapter9/concatenate_strings.py: -------------------------------------------------------------------------------- 1 | # new_module.py 2 | 3 | def concatenate_strings(string_one, string_two): 4 | """ 5 | Concatenates two strings. 6 | 7 | :param string_one: The first string. 8 | :param string_two: The second string. 9 | :return: The concatenation of string_one and string_two. 10 | """ 11 | return a + b 12 | -------------------------------------------------------------------------------- /Chapter9/rollback.py: -------------------------------------------------------------------------------- 1 | mport boto3 2 | 3 | 4 | 5 | def lambda_handler(event, context): 6 | 7 | domain_name = '' 8 | 9 | default_endpoint = '' 10 | 11 | 12 | 13 | # Initialize the Route 53 client 14 | 15 | client = boto3.client('route53') 16 | 17 | 18 | 19 | # Get the hosted zone ID for the domain 20 | 21 | response = client.list_hosted_zones_by_name(DNSName=domain_name) 22 | 23 | hosted_zone_id = response['HostedZoneId'] 24 | 25 | 26 | 27 | # Update the Route 53 record set to point to the default endpoint 28 | 29 | changes= { 30 | 31 | 'Changes': [ 32 | 33 | { 34 | 35 | 'Action': 'UPSERT', 36 | 37 | 'ResourceRecordSet': { 38 | 39 | 'Name': domain_name, 40 | 41 | 'Type': 'A', 42 | 43 | 'TTL': 300, 44 | 45 | 'ResourceRecords': [{'Value': default_endpoint}] 46 | 47 | } 48 | 49 | } 50 | 51 | ] 52 | 53 | } 54 | 55 | 56 | 57 | client.change_resource_record_sets( 58 | 59 | HostedZoneId=hosted_zone_id, 60 | 61 | ChangeBatch=changes 62 | 63 | ) 64 | 65 | 66 | 67 | return { 68 | 69 | 'statusCode': 200, 70 | 71 | 'body': "Nothing, really, no one’s gonna see this}" 72 | 73 | } 74 | -------------------------------------------------------------------------------- /Chapter9/todoist.py: -------------------------------------------------------------------------------- 1 | from todoist_api_python.api import TodoistAPI 2 | import json 3 | from datetime import datetime, timezone 4 | import requests 5 | 6 | api = TodoistAPI("") 7 | access_token = "" 8 | 9 | #Endpoint for your default task list 10 | TODO_API_ENDPOINT = 'https://graph.microsoft.com/v1.0/me/todo/lists/@default/tasks' 11 | 12 | def create_todo_task(title,date): 13 | headers = { 14 | 'Authorization': 'Bearer '+access_token, 15 | 'Content-Type': 'application/json' 16 | } 17 | 18 | payload = { 19 | 'title': title, 20 | 'dueDateTime': date 21 | } 22 | 23 | response = requests.post(TODO_API_ENDPOINT, headers=headers, json=payload) 24 | return response.json() if response.status_code == 201 else None 25 | 26 | try: 27 | tasks = json.dumps(api.get_tasks(),default=lambda o: o.__dict__,sort_keys=True, indent=4) 28 | for task in tasks: 29 | title = task["content"] 30 | date = task["due"]["date"].replace(tzinfo=timezone.utc).astimezone(tz=None) 31 | create_todo_task(title, date) 32 | except Exception as error: 33 | print(error) 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hands-On Python for DevOps 2 | 3 | 4 | 5 | This is the code repository for [Hands-On Python for DevOps](https://www.packtpub.com/product/hands-on-python-for-devops/9781835081167?utm_source=github&utm_medium=repository&utm_campaign=9781835081167), published by Packt. 6 | 7 | **Leverage Python's native libraries to streamline your workflow and save time with automation** 8 | 9 | ## What is this book about? 10 | Unleash the power of Python in DevOps with this comprehensive guide to integrating Python into DevOps workflows to automate tasks, enhance CI/CD pipelines, and delve into MLOps and DataOps to streamline operations and boost efficiency. 11 | 12 | This book covers the following exciting features: 13 | * Implement DevOps practices and principles using Python 14 | * Enhance your DevOps workloads with Python 15 | * Create Python-based DevOps solutions to improve your workload efficiency 16 | * Understand DevOps objectives and the mindset needed to achieve them 17 | * Use Python to automate DevOps tasks and increase productivity 18 | * Explore the concepts of DevSecOps, MLOps, DataOps, and more 19 | * Use Python for containerized workloads in Docker and Kubernetes 20 | 21 | If you feel this book is for you, get your [copy](https://www.amazon.com/dp/1835081169) today! 22 | 23 | https://www.packtpub.com/ 25 | 26 | ## Instructions and Navigations 27 | All of the code is organized into folders. For example, Chapter02. 28 | 29 | The code will look like the following: 30 | ``` 31 | def packet_handler(packet): 32 | print(packet) 33 | packet_sizes.append(len(packet)) 34 | timestamps.append(packet.time) 35 | ``` 36 | 37 | **Following is what you need for this book:** 38 | This book is for IT professionals venturing into DevOps, particularly programmers seeking to apply their existing programming knowledge to excel in this field. For DevOps professionals without a coding background, this book serves as a resource to enhance their understanding of development practices and communicate more effectively with developers. Solutions architects, programmers, and anyone regularly working with DevOps solutions and Python will also benefit from this hands-on guide. 39 | 40 | With the following software and hardware list you can run all code files present in the book (Chapter 1-13). 41 | ### Software and Hardware List 42 | | Chapter | Software required | OS required | 43 | | -------- | ------------------------------------ | ----------------------------------- | 44 | | 1-13 | Python 3.9 or higher | Windows, macOS, or Linux | 45 | | 1-13 | Amazon Web Services (AWS) | Windows, macOS, or Linux | 46 | | 1-13 | Google Cloud Platform (GCP) | Windows, macOS, or Linux | 47 | | 1-13 | Microsoft Azure | Windows, macOS, or Linux | 48 | | 1-13 | Google Colab | Windows, macOS, or Linux | 49 | | 1-13 | Grafana | Windows, macOS, or Linux | 50 | 51 | 52 | 53 | ### Related products 54 | * Go for DevOps [[Packt]](https://www.packtpub.com/product/go-for-devops/9781801818896?utm_source=github&utm_medium=repository&utm_campaign=9781801818896) [[Amazon]](https://www.amazon.com/dp/1801818894) 55 | 56 | * Python Essentials for AWS Cloud Developers [[Packt]](https://www.packtpub.com/product/python-essentials-for-aws-cloud-developers/9781804610060?utm_source=github&utm_medium=repository&utm_campaign=9781804610060) [[Amazon]](https://www.amazon.com/dp/1804610062) 57 | 58 | ## Get to Know the Author 59 | **Ankur Roy** 60 | is a Solutions Architect at Online Partner AB in Stockholm, Sweden. Prior to this, he worked as a Software Engineer at Genese Solution in Kathmandu, Nepal. His areas of expertise include cloud-based solutions and workloads in a diverse range of fields such as development, DevOps, and security, among others. Ankur is an avid blogger, podcaster, content creator, and contributing member of the Python, DevOps, and cloud computing community. He has completed all the available certifications in Google Cloud and several others in AWS and Azure as well. Moreover, he is an AWS Community Builder. 61 | 62 | --------------------------------------------------------------------------------