Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates for Summer 2024 Semester #38

Merged
merged 7 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,20 @@
"customizations": {
"vscode": {
"settings": {
"cSpell.words": [
"Rofrano",
"sqlalchemy",
"psycopg",
"pytest",
"tekton",
"creds",
"virtualenvs"
],
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.formatOnSave": true
},
"git.mergeEditor": true,
"markdown-preview-github-styles.colorTheme": "light",
"makefile.extensionOutputFolder": "/tmp",
"python.testing.unittestEnabled": false,
Expand All @@ -36,36 +46,32 @@
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"VisualStudioExptTeam.vscodeintellicode",
"ms-python.pylint",
"ms-python.flake8",
"ms-python.black-formatter",
"ms-vscode.makefile-tools",
"cstrap.flask-snippets",
"wholroyd.jinja",
"ms-vscode.makefile-tools",
"yzhang.markdown-all-in-one",
"DavidAnson.vscode-markdownlint",
"bierner.github-markdown-preview",
"hnw.vscode-auto-open-markdown-preview",
"davidanson.vscode-markdownlint",
"bierner.markdown-preview-github-styles",
"tamasfe.even-better-toml",
"donjayamanne.githistory",
"GitHub.vscode-pull-request-github",
"github.vscode-github-actions",
"hbenl.vscode-test-explorer",
"LittleFoxTeam.vscode-python-test-adapter",
"njpwerner.autodocstring",
"wholroyd.jinja",
"redhat.vscode-yaml",
"rangav.vscode-thunder-client",
"redhat.fabric8-analytics",
"streetsidesoftware.code-spell-checker",
"ms-azuretools.vscode-docker",
"ms-kubernetes-tools.vscode-kubernetes-tools",
"github.vscode-github-actions",
"inercia.vscode-k3d",
"rangav.vscode-thunder-client",
"alexkrechik.cucumberautocomplete",
"Zignd.html-css-class-completion",
"streetsidesoftware.code-spell-checker",
"streetsidesoftware.code-spell-checker",
"bbenoist.vagrant"
]
}
Expand Down
8 changes: 7 additions & 1 deletion .devcontainer/scripts/install-tools.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ sudo sh -c 'echo "127.0.0.1 cluster-registry" >> /etc/hosts'
echo "**********************************************************************"
echo "Installing K9s..."
echo "**********************************************************************"
curl -L -o k9s.tar.gz "https://github.com/derailed/k9s/releases/download/v0.27.3/k9s_Linux_$ARCH.tar.gz"
curl -L -o k9s.tar.gz "https://github.com/derailed/k9s/releases/download/v0.32.5/k9s_Linux_$ARCH.tar.gz"
tar xvzf k9s.tar.gz
sudo install -c -m 0755 k9s /usr/local/bin
rm k9s.tar.gz
Expand All @@ -34,3 +34,9 @@ echo "Installing Skaffold..."
echo "**********************************************************************"
curl -Lo skaffold "https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-$ARCH"
sudo install skaffold /usr/local/bin/

echo "**********************************************************************"
echo "Installing DevSpace..."
echo "**********************************************************************"
curl -Lo devspace "https://github.com/loft-sh/devspace/releases/latest/download/devspace-linux-$ARCH"
sudo install -c -m 0755 devspace /usr/local/bin
22 changes: 16 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# These can be overidden with env vars.
REGISTRY ?= cluster-registry:32000
REGISTRY ?= cluster-registry:5000
NAMESPACE ?= nyu-devops
IMAGE_NAME ?= lab-flask-bdd
IMAGE_TAG ?= 1.0
IMAGE_NAME ?= petshop
IMAGE_TAG ?= 1.0.0
IMAGE ?= $(REGISTRY)/$(NAMESPACE)/$(IMAGE_NAME):$(IMAGE_TAG)
PLATFORM ?= "linux/amd64,linux/arm64"
CLUSTER ?= nyu-devops
Expand Down Expand Up @@ -61,7 +61,7 @@ secret: ## Generate a secret hex key
.PHONY: cluster
cluster: ## Create a K3D Kubernetes cluster with load balancer and registry
$(info Creating Kubernetes cluster with a registry and 1 node...)
k3d cluster create nyu-devops --agents 1 --registry-create cluster-registry:0.0.0.0:32000 --port '8080:80@loadbalancer'
k3d cluster create nyu-devops --agents 1 --registry-create cluster-registry:0.0.0.0:5000 --port '8080:80@loadbalancer'

.PHONY: cluster-rm
cluster-rm: ## Remove a K3D Kubernetes cluster
Expand All @@ -71,15 +71,25 @@ cluster-rm: ## Remove a K3D Kubernetes cluster
##@ Deploy

.PHONY: push
image-push: ## Push to a Docker image registry
push: ## Push to a Docker image registry
$(info Logging into IBM Cloud cluster $(CLUSTER)...)
docker push $(IMAGE)

.PHONY: postgres
postgres: ## Deploy the PostgreSQL service on local Kubernetes
$(info Deploying PostgreSQL service to Kubernetes...)
kubectl apply -f k8s/postgres

.PHONY: deploy
deploy: ## Deploy the service on local Kubernetes
deploy: postgres ## Deploy the service on local Kubernetes
$(info Deploying service locally...)
kubectl apply -f k8s/

.PHONY: undeploy
undeploy: ## Delete the deployment on local Kubernetes
$(info Removing service on Kubernetes...)
kubectl delete -f k8s/

############################################################
# COMMANDS FOR BUILDING THE IMAGE
############################################################
Expand Down
48 changes: 45 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,64 @@ Pytest is configured to automatically include the flags `--pspec --cov=service -

These tests require the service to be running because unlike the the TDD unit tests that test the code locally, these BDD integration tests are using Selenium to manipulate a web page on a running server.

Run the tests using `behave`
#### Run using two shells

Start the server in a separate bash shell:

```sh
honcho start
```

Then start behave in your original bash shell:
Then start `behave` in your original bash shell:

```sh
behave
```

You will see the results of the tests scroll down yur screen using the familiar red/green/refactor colors.

#### Run using Kubernetes

You can also use Kubernetes to host your application and test against it with BDD. The commands to do this are:

```bash
make cluster
make build
make push
make deploy
```

What did these commands do?

| Command | What does it do? |
|---------|------------------|
| make cluster | Creates a local Kubernetes cluster using `k3d` |
| make build | Builds the Docker image |
| make push | Pushes the image to the local Docker registry |
| make deploy | Deploys the application using the image that was just built and pushed |

Now you can just run `behave` against the application running in the local Kubernetes cluster

```bash
behave
```

### See what images are in the local registry

You can use the `curl` command to query what images you have pushed to your local Docker registry. This will return `JSON` so you might want to use the silent flag `-s` and pipe it through `jq` like this:

```bash
curl -XGET http://localhost:5000/v2/_catalog -s | jq
```

That will return all of the image names without the tags.

To get the tags use:

```bash
curl -XGET http://localhost:5000/v2/<image-name>/tags/list -s | jq
```

## What's featured in the project?

```text
Expand All @@ -108,7 +150,7 @@ You will see the results of the tests scroll down yur screen using the familiar

## License

Copyright (c) 2016, 2023, John J. Rofrano. All rights reserved.
Copyright (c) 2016, 2024, John J. Rofrano. All rights reserved.

Licensed under the Apache License. See [LICENSE](LICENSE)

Expand Down
3 changes: 2 additions & 1 deletion features/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def get_chrome():
"""Creates a headless Chrome driver"""
options = webdriver.ChromeOptions()
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--headless")
return webdriver.Chrome(options=options)

Expand All @@ -43,4 +44,4 @@ def get_firefox():
options = webdriver.FirefoxOptions()
options.add_argument("--headless")
return webdriver.Firefox(options=options)


23 changes: 14 additions & 9 deletions features/steps/pets_steps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
######################################################################
# Copyright 2016, 2023 John J. Rofrano. All Rights Reserved.
# Copyright 2016, 2024 John J. Rofrano. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -23,24 +23,29 @@
https://selenium-python.readthedocs.io/waits.html
"""
import requests
from behave import given
from compare3 import expect
from behave import given # pylint: disable=no-name-in-module

# HTTP Return Codes
HTTP_200_OK = 200
HTTP_201_CREATED = 201
HTTP_204_NO_CONTENT = 204

WAIT_TIMEOUT = 60


@given('the following pets')
def step_impl(context):
""" Delete all Pets and load new ones """

# List all of the pets and delete them one by one
# Get a list all of the pets
rest_endpoint = f"{context.base_url}/pets"
context.resp = requests.get(rest_endpoint)
assert(context.resp.status_code == HTTP_200_OK)
context.resp = requests.get(rest_endpoint, timeout=WAIT_TIMEOUT)
expect(context.resp.status_code).equal_to(HTTP_200_OK)
# and delete them one by one
for pet in context.resp.json():
context.resp = requests.delete(f"{rest_endpoint}/{pet['id']}")
assert(context.resp.status_code == HTTP_204_NO_CONTENT)
context.resp = requests.delete(f"{rest_endpoint}/{pet['id']}", timeout=WAIT_TIMEOUT)
expect(context.resp.status_code).equal_to(HTTP_204_NO_CONTENT)

# load the database with new pets
for row in context.table:
Expand All @@ -51,5 +56,5 @@ def step_impl(context):
"gender": row['gender'],
"birthday": row['birthday']
}
context.resp = requests.post(rest_endpoint, json=payload)
assert(context.resp.status_code == HTTP_201_CREATED)
context.resp = requests.post(rest_endpoint, json=payload, timeout=WAIT_TIMEOUT)
expect(context.resp.status_code).equal_to(HTTP_201_CREATED)
4 changes: 2 additions & 2 deletions features/steps/web_steps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
######################################################################
# Copyright 2016, 2023 John J. Rofrano. All Rights Reserved.
# Copyright 2016, 2024 John J. Rofrano. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -25,7 +25,7 @@
https://selenium-python.readthedocs.io/waits.html
"""
import logging
from behave import when, then
from behave import when, then # pylint: disable=no-name-in-module
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select, WebDriverWait
from selenium.webdriver.support import expected_conditions
Expand Down
8 changes: 4 additions & 4 deletions k3d-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
apiVersion: k3d.io/v1alpha3
kind: Simple
name: devops
name: nyu-devops
servers: 1
agents: 1
ports:
Expand All @@ -11,9 +11,9 @@ registries:
create:
name: cluster-registry
host: "0.0.0.0"
hostPort: "32000"
hostPort: "5000"
config: |
mirrors:
"cluster-registry:32000":
"cluster-registry":
endpoint:
- http://cluster-registry:32000
- http://cluster-registry:5000
18 changes: 8 additions & 10 deletions k8s/deployment.yaml
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: lab-flask-bdd
name: petshop
labels:
app: lab-flask-bdd
app: petshop
spec:
replicas: 2
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 0%
maxUnavailable: 50%
selector:
matchLabels:
app: lab-flask-bdd
app: petshop
template:
metadata:
labels:
app: lab-flask-bdd
app: petshop
spec:
imagePullSecrets:
- name: all-icr-io
restartPolicy: Always
containers:
- name: lab-flask-bdd
# image: cluster-registry:32000/lab-flask-bdd:1.0
image: lab-flask-bdd
- name: petshop
image: cluster-registry:5000/nyu-devops/petshop:1.0.0
# image: petshop
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
Expand Down
4 changes: 2 additions & 2 deletions k8s/ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: lab-flask-bdd
name: petshop
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
Expand All @@ -13,6 +13,6 @@ spec:
pathType: Prefix
backend:
service:
name: lab-flask-bdd
name: petshop
port:
number: 8080
1 change: 0 additions & 1 deletion k8s/pv.yaml → k8s/postgres/pv.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@ spec:
persistentVolumeReclaimPolicy: Recycle
hostPath:
path: /data/pv0001
storageClassName: "default"
11 changes: 11 additions & 0 deletions k8s/postgres/pvc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
File renamed without changes.
14 changes: 14 additions & 0 deletions k8s/postgres/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
apiVersion: v1
kind: Service
metadata:
name: postgres
labels:
app: postgres
spec:
type: ClusterIP
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
Loading
Loading