Wave changes
This commit is contained in:
52
Career Concepts/20250722221649-career_moc.org
Normal file
52
Career Concepts/20250722221649-career_moc.org
Normal file
@@ -0,0 +1,52 @@
|
||||
:PROPERTIES:
|
||||
:ID: dd04d228-fff5-402a-929d-9d113a2ec965
|
||||
:DATE_STARTED: <2025-07-22 Tue>
|
||||
:END:
|
||||
#+STARTUP: overview
|
||||
#+title: career_moc
|
||||
#+filetags: :moc:career:
|
||||
|
||||
Here will lie articles, resources, notes and the like relating to my career. It differ with [[https://www.zainezq.com/posts/career/career-list.html][this]] page in the sense that this one will contain:
|
||||
|
||||
- Ideas
|
||||
- Thoughts
|
||||
- Notes
|
||||
- Videos to watch
|
||||
- Articles to read
|
||||
- Resources to check out
|
||||
- And other things
|
||||
|
||||
Whereas [[https://www.zainezq.com/posts/career/career-list.html][this]] page will contain /finished/ notes regarding what I'm learning at different points in my career. For instance, the majority of November was learning about Software Engineering principles; things like requirements, user stories, lean and retrospectives.
|
||||
|
||||
* Notes
|
||||
[[id:56fabaf6-e8aa-45d0-a1c1-89f247f0a93f][APIM]]
|
||||
|
||||
* Unread Articles
|
||||
|
||||
- https://www.finalroundai.com/blog/why-vibe-coding-leaves-you-with-skills-that-dont-last
|
||||
|
||||
- https://forge.medium.com/a-simple-tool-for-personal-growth-dc1e822aa229
|
||||
|
||||
- https://medium.com/@saiyaff/ai-tools-and-the-software-engineers-dilemma-e4ad89d516ca
|
||||
* Read Articles
|
||||
|
||||
* Coding
|
||||
- [[id:2729599d-ae2b-4f22-b73d-bf22d81e0767][test-driven-development]]
|
||||
|
||||
* Microlise
|
||||
|
||||
[[id:ABF4A0BE-0309-48A6-92ED-76031B3D2F86][microlise_moc]]
|
||||
|
||||
* Interview preps
|
||||
|
||||
- [[id:f9897f8e-2b63-4ad2-a55f-3787c4ac235f][job_application_cover_letters]]
|
||||
- [[id:5cfd7f6f-f5ac-4f18-90f9-be9a31dd238e][java-portswrigger-test]]
|
||||
|
||||
* Resources:
|
||||
** Links
|
||||
- [[https://simpleprogrammer.com/my-free-blogging-course-is-getting-unbelievable-results/][Simple Programmer]]
|
||||
** Books
|
||||
- [[file:/home/zaine/master-folder/pdfs/technical/sicp.pdf][SICP Book]]
|
||||
|
||||
|
||||
|
||||
9
Career Concepts/20250723200800-postgres.org
Normal file
9
Career Concepts/20250723200800-postgres.org
Normal file
@@ -0,0 +1,9 @@
|
||||
:PROPERTIES:
|
||||
:ID: 939e301b-6463-46a8-b57e-0af606e7e7ef
|
||||
:END:
|
||||
#+title: Postgres
|
||||
#+filetags: :database:index:
|
||||
|
||||
#+begin_src bash
|
||||
psql -h 82.18.104.48 -p 5432 -U zaine -d org_web
|
||||
#+end_src
|
||||
9
Career Concepts/20250727122406-database_moc.org
Normal file
9
Career Concepts/20250727122406-database_moc.org
Normal file
@@ -0,0 +1,9 @@
|
||||
:PROPERTIES:
|
||||
:ID: e448cd99-afee-4702-947f-644bb34dc1aa
|
||||
:END:
|
||||
#+title: Database MOC
|
||||
#+filetags: :database:moc:
|
||||
|
||||
- [[id:939e301b-6463-46a8-b57e-0af606e7e7ef][Postgres]]
|
||||
|
||||
- [[id:c6cf8f7a-778f-4e83-b607-753ef8dbb3f1][Airflow]]
|
||||
115
Career Concepts/20250804201706-big_o_complexity.org
Normal file
115
Career Concepts/20250804201706-big_o_complexity.org
Normal file
@@ -0,0 +1,115 @@
|
||||
:PROPERTIES:
|
||||
:ID: 275988a8-59d8-40c8-a8b4-47118d6eb834
|
||||
:END:
|
||||
#+title: Big (O) - Time and Space Complexity
|
||||
#+filetags: :leetcode:notes:
|
||||
#+OPTIONS: toc:t
|
||||
#+category: Career Concepts
|
||||
|
||||
* Big (O) - Time and Space Complexity
|
||||
** Intro
|
||||
Time Complexity: Describes the amount of time necessary to execute an algorithm
|
||||
|
||||
Space Complexity: Describes the amount of memory or space utilized by an algorithm/program
|
||||
|
||||
Both - asymptotically
|
||||
|
||||
|
||||
** Technical Definition of Big O
|
||||
|
||||
is a mathematical notation that describes the limiting behaviour of a function when the arguments tend towards a particular value or infinity. Why do we need it? it helps us understand how the performance of an algorithm changes as the size of the input grows, providing a simple way to compare and analyse different algorithms' efficiency.
|
||||
|
||||
Improvement in time complexity is often more important as memory is cheap and readily available
|
||||
|
||||
In Big O, there are six major types of complexities (time and space):
|
||||
|
||||
- Constant: O(1)
|
||||
|
||||
- Linear time: O(n)
|
||||
|
||||
- Logarithmic time: O(n log n)
|
||||
|
||||
- Quadratic time: O(n^2)
|
||||
|
||||
- Exponential time: O(2^n)
|
||||
|
||||
- Factorial time: O(n!)
|
||||
|
||||
|
||||
** Big O - linear example
|
||||
|
||||
Suppose we are given a problem where we have a list of `N` numbers of unknown length. We are asked to use code to find and return "True" if the number 2 is in the list and "False" otherwise. Our solution could be to go through every position in the list and check if the number at that position is equal to 2.
|
||||
|
||||
[3, 10, 2, 7]
|
||||
|
||||
#+begin_src python
|
||||
for number in list:
|
||||
if number == 2:
|
||||
return True
|
||||
else:
|
||||
continue
|
||||
return False
|
||||
#+end_src
|
||||
|
||||
This would take N time, we need to check every number in the list once, making this solution O(N) - linear time. This looks at the worst case scenarion, if 2 was at the start of the list we know it would take a constant time, however if it's at the end then it would take N time.
|
||||
|
||||
[[../assets/Big-O-Notation-3130482830.png]]
|
||||
|
||||
In the graph above focus on the tail end of the graphs because Big O is concerned with "as the input size grows what happens to the speed of the operations".
|
||||
|
||||
+------------+--------------+----------------------------------+------------------------------------+----------------------+
|
||||
| Complexity | Name | Description | Common Use Cases | Performance at Scale |
|
||||
+------------+--------------+----------------------------------+------------------------------------+----------------------+
|
||||
| O(1) | Constant | Runtime unaffected by input size | Hash tables, array access | Excellent |
|
||||
+------------+--------------+----------------------------------+------------------------------------+----------------------+
|
||||
| O(log n) | Logarithmic | Runtime increases slowly | Binary search, balanced trees | Very good |
|
||||
| | | (typically halved at each step) | | |
|
||||
+------------+--------------+----------------------------------+------------------------------------+----------------------+
|
||||
| O(n) | Linear | Runtime scales linearly | Linear search, array traversal | Good |
|
||||
| | | (proportional) | | |
|
||||
+------------+--------------+----------------------------------+------------------------------------+----------------------+
|
||||
| O(n log n) | Linearithmic | Between linear and quadratic | Efficient sorting algorithms | Fair |
|
||||
| | | (often seen in divide and conquer| | |
|
||||
| | | algorithms) | | |
|
||||
+------------+--------------+----------------------------------+------------------------------------+----------------------+
|
||||
| O(n²) | Quadratic | Runtime squares with input size | Nested loops, simple sorting | Poor |
|
||||
+------------+--------------+----------------------------------+------------------------------------+----------------------+
|
||||
| O(2ⁿ) | Exponential | Runtime doubles with each input | Recursive solutions, combinatorics | Very poor |
|
||||
+------------+--------------+----------------------------------+------------------------------------+----------------------+
|
||||
| O(n!) | Factorial | Runtime grows by factorial | Permutations, traveling salesman | Terrible |
|
||||
| | | (extremely slow) | | |
|
||||
+------------+--------------+----------------------------------+------------------------------------+----------------------+
|
||||
|
||||
|
||||
** Summation of complexities:
|
||||
|
||||
When you have multiple operations in an algorithm that each have a linear time complexity O(n), and these operations are sequential (not nested), the overall time complexity of the algorithm remains linear, O(n).
|
||||
|
||||
Here's how it works:
|
||||
|
||||
1. Summing Linear Operations: If your algorithm involves several separate linear operations, such as:
|
||||
• First iterating over an array of n elements,
|
||||
• Then, in a separate loop, iterating over the same or another array of n elements,
|
||||
• And perhaps another loop doing the same,
|
||||
each operation has a complexity of O(n). If you sum these, the resulting complexity for these sequential operations is O(n) + O(n) + O(n), and so on.
|
||||
|
||||
2. Simplification: According to Big O notation rules, when you add complexities of the same order, the overall complexity is dominated by the term that grows fastest as n increases. For linear operations, O(n) + O(n) + O(n) simplifies to O(n) because the growth rate in terms of the largest input size n doesn't change-it remains linear.
|
||||
|
||||
|
||||
Linear time complexity, denoted as O(n), means that the time required to complete the execution of an algorithm increases linearly with the increase in the size of the input data. In essence, if you double the size of the input, you double the time it takes to process it.
|
||||
|
||||
Suppose you have a task to sum the number 5, n times. The number of operations (in this case, additions) you perform directly corresponds to n. For instance:
|
||||
|
||||
- If n = 1, you perform the operation 1 time: 5.
|
||||
- If n = 2, you perform the operation 2 times: 5+5.
|
||||
- If n = 3, you perform the operation 3 times: 5+5+5.
|
||||
- And so on...
|
||||
|
||||
In each of these cases, the number of addition operations you perform is exactly equal to n. The computational cost grows directly with n, which is the very definition of linear time complexity. Here's a breakdown:
|
||||
|
||||
- When n = 1, the number of operations is 1.
|
||||
- When n = 10, the number of operations is 10.
|
||||
- When n = 100, the number of operations is 100.
|
||||
- When n = 1000, the number of operations is 1000.
|
||||
|
||||
In general, the total time taken for this task can be described as a function T(n) = n, where T(n) represents the total time or total number of operations, and n is the number of times you need to add 5. This function is a straight line when plotted against n, hence it is classified under linear time complexity O(n).
|
||||
156
Career Concepts/20251223215636-design_patterns_notes.org
Normal file
156
Career Concepts/20251223215636-design_patterns_notes.org
Normal file
@@ -0,0 +1,156 @@
|
||||
:PROPERTIES:
|
||||
:ID: 631b2086-4b8f-4fe3-829d-be1dc014e293
|
||||
:END:
|
||||
#+title: Design patterns
|
||||
#+filetags: :notes:career:technical:
|
||||
#+category: Career Concepts
|
||||
|
||||
*WIP*
|
||||
|
||||
* Summary of the major patterns:
|
||||
|
||||
** The Strategy Pattern
|
||||
Strategy is a behavioral design pattern that lets you define a family of algorithms, put each of them into a separate class, and make their objects interchangeable.
|
||||
|
||||
[[./assets/design-patterns/structure-pattern.png]]
|
||||
|
||||
|
||||
|
||||
** Observer pattern
|
||||
Observer is a behavioral design pattern that lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they’re observing.
|
||||
|
||||
[[./assets/design-patterns/observer-pattern.png]]
|
||||
|
||||
|
||||
** Decorator pattern
|
||||
|
||||
Decorator is a structural design pattern that lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors.
|
||||
|
||||
The problem:
|
||||
|
||||
[[./assets/design-patterns/decorator-problem.png]]
|
||||
|
||||
[[./assets/design-patterns/decorator-pattern.png]]
|
||||
|
||||
|
||||
** Factory Pattern
|
||||
Factory Method is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.
|
||||
|
||||
[[./assets/design-patterns/factory-pattern.png]]
|
||||
|
||||
|
||||
** Singleton Pattern
|
||||
Singleton is a creational design pattern that lets you ensure that a class has only one instance, while providing a global access point to this instance.
|
||||
|
||||
[[./assets/design-patterns/singleton-pattern.png]]
|
||||
|
||||
|
||||
** Command Pattern
|
||||
Command is a behavioral design pattern that turns a request into a stand-alone object that contains all information about the request. This transformation lets you pass requests as a method arguments, delay or queue a request’s execution, and support undoable operations.
|
||||
|
||||
[[./assets/design-patterns/command-pattern.png]]
|
||||
|
||||
|
||||
** Adapter Pattern
|
||||
Adapter is a structural design pattern that allows objects with incompatible interfaces to collaborate.
|
||||
|
||||
[[./assets/design-patterns/adapter-pattern.png]]
|
||||
|
||||
Another approach:
|
||||
|
||||
[[./assets/design-patterns/adapter-pattern-2.png]]
|
||||
|
||||
** Facade Pattern
|
||||
Facade is a structural design pattern that provides a simplified interface to a library, a framework, or any other complex set of classes.
|
||||
|
||||
[[./assets/design-patterns/facade-pattern.png]]
|
||||
|
||||
|
||||
** Template Method Pattern
|
||||
Template Method is a behavioral design pattern that defines the skeleton of an algorithm in the superclass but lets subclasses override specific steps of the algorithm without changing its structure.
|
||||
|
||||
[[./assets/design-patterns/template-method-pattern.png]]
|
||||
|
||||
** Iterator and Composite Pattern
|
||||
Iterator is a behavioral design pattern that lets you traverse elements of a collection without exposing its underlying representation (list, stack, tree, etc.).
|
||||
|
||||
[[./assets/design-patterns/iterator-pattern.png]]
|
||||
|
||||
Composite is a structural design pattern that lets you compose objects into tree structures and then work with these structures as if they were individual objects.
|
||||
|
||||
[[./assets/design-patterns/composite-pattern.png]]
|
||||
|
||||
** State Pattern
|
||||
State is a behavioral design pattern that lets an object alter its behavior when its internal state changes. It appears as if the object changed its class.
|
||||
|
||||
[[./assets/design-patterns/state-pattern.png]]
|
||||
|
||||
** Proxy Pattern
|
||||
Proxy is a structural design pattern that lets you provide a substitute or placeholder for another object. A proxy controls access to the original object, allowing you to perform something either before or after the request gets through to the original object.
|
||||
|
||||
[[./assets/design-patterns/proxy-pattern.png]]
|
||||
|
||||
* Design patterns. What are they?
|
||||
|
||||
They are reusable solutions to common problems in software design. They help to make code more flexible, maintainable, and scalable.
|
||||
|
||||
Patterns allow you to say more with less. When you use a pattern in a description, other developers quickly know precisely the design you have in mind.
|
||||
|
||||
** OO concepts:
|
||||
*** Abstraction:
|
||||
Focuses on essential features while hiding unnecessary internal details, allowing developers to work with high‑level concepts instead of implementation complexity.
|
||||
|
||||
Example: A Car class exposes start() and stop() methods without revealing how the engine ignition system works.
|
||||
|
||||
*** Inheritance:
|
||||
Enables one class to derive properties and behaviours from another, promoting code reuse and creating natural parent–child hierarchies.
|
||||
|
||||
Example: A Dog class inherits from an Animal class, automatically gaining attributes like age and methods like eat().
|
||||
|
||||
*** Encapsulation:
|
||||
Protects an object’s internal state by restricting direct access to its data and exposing controlled interfaces for interaction.
|
||||
|
||||
Example: A BankAccount class keeps its balance private and provides deposit() and withdraw() methods to modify it safely.
|
||||
|
||||
*** Polymorphism:
|
||||
Allows different objects to respond to the same interface or method call in their own unique ways, enabling flexible and extensible system design.
|
||||
|
||||
Example: Calling makeSound() on an Animal reference triggers bark() for a Dog and meow() for a Cat.
|
||||
|
||||
** OO principles:
|
||||
|
||||
- Encapsulate what varies
|
||||
|
||||
- Favor composition over inheritance
|
||||
|
||||
- Program to interfaces, not implementations
|
||||
|
||||
- Strive for loosely coupled designs between objects that interact
|
||||
|
||||
** OO Patterns
|
||||
|
||||
You have:
|
||||
- *behavioural* patterns
|
||||
- *creational* patterns
|
||||
- *structural* patterns
|
||||
|
||||
*** Behavioural patterns
|
||||
**** Structural:
|
||||
The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
|
||||
**** Observer:
|
||||
The Observer Pattern defines a one-to-many dependency between objects so that when
|
||||
one object changes state, all of its dependents are notified and updated automatically.
|
||||
|
||||
Subjects, or as we also know them, Observables, update Observers using a common
|
||||
interface
|
||||
|
||||
Observers are loosely coupled in that the Observable knows nothing about them,
|
||||
other than that they implement the Observer interface.
|
||||
|
||||
You can push or pull data from the Observable when using the pattern (pull is
|
||||
considered more “correct”).
|
||||
|
||||
Don’t depend on a specific order of notification for your Observers.
|
||||
|
||||
Java has several implementations of the Observer Pattern, including the general
|
||||
purpose java.util.Observable
|
||||
25
Career Concepts/20251229180039-airflow.org
Normal file
25
Career Concepts/20251229180039-airflow.org
Normal file
@@ -0,0 +1,25 @@
|
||||
:PROPERTIES:
|
||||
:ID: c6cf8f7a-778f-4e83-b607-753ef8dbb3f1
|
||||
:END:
|
||||
#+title: Airflow
|
||||
#+filetags: :database:docs:
|
||||
|
||||
* xcom
|
||||
|
||||
XComs stands for cross-communications, and as the name suggests, it allows [[id:1ea42d73-3cd1-4cac-a6ee-028de21d08d5][Airflow Tasks]] to talk to each other (because by default, tasks are entirely isolated and can run on seperate machines).
|
||||
|
||||
See [[https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/xcoms.html][this]]
|
||||
|
||||
* parquets
|
||||
*Key Takeaways*
|
||||
|
||||
- What is Parquet: An open-source columnar storage file format for efficient analytics.
|
||||
- Core Benefits: Superior compression, faster query performance (via column pruning and predicate pushdown), and schema evolution support.
|
||||
- Common Alternatives: Compared to row-based (CSV, Avro), columnar (ORC), and table formats (Iceberg, Delta Lake).
|
||||
- DuckDB & MotherDuck: Parquet integrates seamlessly with DuckDB for high-performance SQL queries directly on Parquet files.
|
||||
|
||||
*What is Parquet?*
|
||||
|
||||
Parquet is a columnar storage file format. When data engineers ask 'what is a Parquet file?', the simple answer is that it's a file that stores data in columns, not rows. This Parquet data format is designed for efficient data processing, particularly in the context of big data applications. Developed as part of the Apache Hadoop ecosystem, Parquet has gained widespread adoption due to its ability to optimize storage and query performance.
|
||||
|
||||
[[https://motherduck.com/learn-more/why-choose-parquet-table-file-format/][See this]]
|
||||
14
Career Concepts/20251229180156-airflow_tasks.org
Normal file
14
Career Concepts/20251229180156-airflow_tasks.org
Normal file
@@ -0,0 +1,14 @@
|
||||
:PROPERTIES:
|
||||
:ID: 1ea42d73-3cd1-4cac-a6ee-028de21d08d5
|
||||
:END:
|
||||
#+title: Airflow Tasks
|
||||
#+filetags: :airflow:database:definitions:
|
||||
|
||||
A task in the context of airflow is the basic unit of execution. They are arranged into [[id:3b16e19a-62f0-4705-a451-a8790181941f][Dags]] and then have upstream and downstream dependencies set between them in order to express the order in which they should be run.
|
||||
|
||||
There are three kinds of tasks:
|
||||
1. Operators: they are predefined task templates that you can string together quickly.
|
||||
2. Sensors: special subclass of operators, which are entirely about waiting for an external event to happen.
|
||||
3. A Taskflow-decorated @task, which is a custom python function packaged as a task.
|
||||
|
||||
[[https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/tasks.html][See this]]
|
||||
7
Career Concepts/20251229180249-airflow_dags.org
Normal file
7
Career Concepts/20251229180249-airflow_dags.org
Normal file
@@ -0,0 +1,7 @@
|
||||
:PROPERTIES:
|
||||
:ID: 3b16e19a-62f0-4705-a451-a8790181941f
|
||||
:END:
|
||||
#+title: Airflow Dags
|
||||
#+filetags: :airflow:database:definitions:
|
||||
|
||||
A DAG (short for directed acyclic graphs) is a model that encapsulates everything needed to execute a workflow. [[https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/dags.html][See this]]
|
||||
109
Career Concepts/20260101010049-concepts.org
Normal file
109
Career Concepts/20260101010049-concepts.org
Normal file
@@ -0,0 +1,109 @@
|
||||
:PROPERTIES:
|
||||
:ID: 22737796-6D31-49D5-84F2-F7BC73E45144
|
||||
:END:
|
||||
#+title: Concepts
|
||||
#+filetags: :technical:concepts:
|
||||
#+category: Career Concepts
|
||||
|
||||
In this node lies notes relating to theoretical concepts tying with maths and/or computer science. I will need to find a way to categorise different notes, but it's a wip.
|
||||
|
||||
* Mathematical Concepts
|
||||
|
||||
Part of being a software engineer is having a good grasp of mathematical concepts. Here are some notes on various mathematical concepts that I find useful.
|
||||
|
||||
- [[id:F32F8F09-3DEC-4FD1-8CFA-401A316E906B][XOR]]
|
||||
|
||||
* Core Programming Concepts
|
||||
|
||||
- [[id:6820973F-613E-441A-BC1D-8FE5CD9BD6F7][Solid Principles]]
|
||||
|
||||
- [[id:275988a8-59d8-40c8-a8b4-47118d6eb834][Big O Notation, Time and Space Complexity]]
|
||||
|
||||
- [[id:631b2086-4b8f-4fe3-829d-be1dc014e293][Design patterns]] WIP
|
||||
|
||||
- [[id:2767b5ac-f2c9-4b1e-ab87-82c43cdec4c1][CI/CD Example - Sitevisits]]
|
||||
|
||||
- [[id:5b714c6c-7eaf-4f3f-b4f6-2166ff3a9963][CI/CD Summary]]
|
||||
|
||||
Some core programming concepts that are essential for software development. The things I need to add here are:
|
||||
|
||||
* APIs
|
||||
|
||||
- [[id:6a5bf6dd-d0ec-43e4-8e07-9956f4715f10][RESTful API]]
|
||||
|
||||
- [[id:49b195c8-e116-40ca-86e8-62c65dbb5a4f][API Architecture]] (Just needs spell checks and re read)
|
||||
|
||||
- [[id:e7f082e4-1b9f-4ebe-96d6-94d92e80a07e][API Intro Notes]]
|
||||
|
||||
- [[id:b2fd7038-42a8-4cbe-882b-92fbe2c12a11][ASP.NET Core Web API Fundamental Notes]]
|
||||
|
||||
* Database Related
|
||||
|
||||
- [[id:b4858f6a-b05c-47f2-972e-905e0bb2c352][Database Permissions, Roles, and Accounts]]
|
||||
|
||||
* Concepts to learn and talk about (cs and maths)
|
||||
- +xor+
|
||||
- +big O notation+
|
||||
- +time complexity+
|
||||
- +space complexity+
|
||||
- data structures
|
||||
- algorithms
|
||||
- design patterns
|
||||
- functional programming
|
||||
- object-oriented programming
|
||||
- relational databases vs non-relational databases
|
||||
- +Database permissions, roles and accounts+
|
||||
- networking basics
|
||||
- operating systems fundamentals
|
||||
- concurrency and parallelism
|
||||
- software development methodologies (Agile, Scrum, etc.)
|
||||
- version control systems (Git, etc.)
|
||||
- testing methodologies (unit testing, integration testing, etc.)
|
||||
- security best practices
|
||||
- cloud computing basics
|
||||
- containerization (Docker, Kubernetes, etc.)
|
||||
- DevOps practices
|
||||
- +CI/CD pipelines+
|
||||
- microservices architecture
|
||||
- API design and development
|
||||
- +restful apis+
|
||||
- web development fundamentals (HTML, CSS, JavaScript)
|
||||
- mobile app development basics
|
||||
- machine learning basics
|
||||
- data science fundamentals
|
||||
- big data concepts
|
||||
- blockchain basics
|
||||
- cryptography fundamentals
|
||||
- user experience (UX) design principles
|
||||
- software architecture patterns (MVC, MVVM, etc.)
|
||||
- debugging techniques
|
||||
- performance optimization strategies
|
||||
- software documentation best practices
|
||||
- ethical considerations in software development
|
||||
- emerging technologies in software development
|
||||
- career development in software engineering
|
||||
- soft skills for software engineers (communication, teamwork, etc.)
|
||||
- project management basics for software projects
|
||||
- open source contribution best practices
|
||||
- remote work best practices for software engineers
|
||||
- continuous learning strategies for software engineers
|
||||
- data types
|
||||
- bytes and bits
|
||||
- number systems (binary, decimal, hexadecimal)
|
||||
- logic gates
|
||||
- set theory
|
||||
- graph theory
|
||||
- combinatorics
|
||||
- probability theory
|
||||
- statistics
|
||||
- linear algebra
|
||||
- calculus
|
||||
- discrete mathematics
|
||||
- compilers
|
||||
- interpreters
|
||||
- automata theory
|
||||
- formal languages
|
||||
- Turing machines
|
||||
- computability theory
|
||||
- MVPs and MVTs
|
||||
|
||||
41
Career Concepts/20260101011126-xor.org
Normal file
41
Career Concepts/20260101011126-xor.org
Normal file
@@ -0,0 +1,41 @@
|
||||
:PROPERTIES:
|
||||
:ID: F32F8F09-3DEC-4FD1-8CFA-401A316E906B
|
||||
:END:
|
||||
#+title: XOR
|
||||
#+filetags: :maths:notes:
|
||||
#+category: Career Concepts
|
||||
|
||||
XOR stands for exclusive or. It is a logical operation that outputs true only when the inputs differ (one is true, the other is false). If both inputs are the same (both true or both false), the output is false.
|
||||
|
||||
Here is the truth table for XOR:
|
||||
|
||||
+-------+-------+---------+
|
||||
| A | B | A XOR B |
|
||||
+-------+-------+---------+
|
||||
| false | false | false |
|
||||
+-------+-------+---------+
|
||||
| false | true | true |
|
||||
+-------+-------+---------+
|
||||
| true | false | true |
|
||||
+-------+-------+---------+
|
||||
| true | true | false |
|
||||
+-------+-------+---------+
|
||||
|
||||
In programming, XOR is often represented by the caret symbol (^). For example, in many programming languages, you can use the XOR operator like this:
|
||||
|
||||
#+begin_src python
|
||||
a = True
|
||||
b = False
|
||||
result = a ^ b # result will be True
|
||||
#+end_src
|
||||
|
||||
In simple terms it means "one or the other, but not both".
|
||||
|
||||
Some similar concepts include:
|
||||
- OR (inclusive or): Outputs true if at least one input is true.
|
||||
- AND: Outputs true only if both inputs are true.
|
||||
- NOT: Outputs the opposite of the input (true becomes false, false becomes true).
|
||||
- NAND: Outputs false only if both inputs are true (the opposite of AND).
|
||||
- NOR: Outputs true only if both inputs are false (the opposite of OR).
|
||||
- XNOR: Outputs true only when both inputs are the same (the opposite of XOR).
|
||||
|
||||
23
Career Concepts/20260101012549-solid_principles.org
Normal file
23
Career Concepts/20260101012549-solid_principles.org
Normal file
@@ -0,0 +1,23 @@
|
||||
:PROPERTIES:
|
||||
:ID: 6820973F-613E-441A-BC1D-8FE5CD9BD6F7
|
||||
:END:
|
||||
#+title: Solid Principles
|
||||
#+filetags: :career:notes:technical:
|
||||
#+category: Career Concepts
|
||||
|
||||
The SOLID principles are a set of five design principles that help software developers create maintainable, scalable, and flexible software systems. The principles were introduced by Robert C. Martin (Uncle Bob) and are widely used in object-oriented programming.
|
||||
|
||||
The SOLID principles are:
|
||||
|
||||
1. **Single Responsibility Principle (SRP)**: A class should have only one reason to change, meaning it should have only one job or responsibility. This makes the class easier to understand and maintain.
|
||||
|
||||
2. **Open/Closed Principle (OCP)**: Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. This means that you should be able to add new functionality without changing existing code, which helps prevent bugs and maintain stability.
|
||||
|
||||
3. **Liskov Substitution Principle (LSP)**: Subtypes must be substitutable for their base types without altering the correctness of the program. This means that objects of a derived class should be able to replace objects of the base class without affecting the behavior of the program.
|
||||
|
||||
4. **Interface Segregation Principle (ISP)**: Clients should not be forced to depend on interfaces they do not use. This means that it's better to have many small, specific interfaces rather than a few large, general ones, which helps reduce dependencies and improve flexibility.
|
||||
|
||||
5. **Dependency Inversion Principle (DIP)**: High-level modules should not depend on low-level modules; both should depend on abstractions. Additionally, abstractions should not depend on details; details should depend on abstractions. This principle encourages the use of interfaces and abstract classes to decouple high-level and low-level components.
|
||||
|
||||
[[id:F3875F0F-5C9E-4BB1-A79C-6000B9558115][solid_principles_examples]]
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
:PROPERTIES:
|
||||
:ID: F3875F0F-5C9E-4BB1-A79C-6000B9558115
|
||||
:END:
|
||||
#+title: solid_principles_examples
|
||||
|
||||
56
Career Concepts/20260115152626-apim.org
Normal file
56
Career Concepts/20260115152626-apim.org
Normal file
@@ -0,0 +1,56 @@
|
||||
:PROPERTIES:
|
||||
:ID: 56fabaf6-e8aa-45d0-a1c1-89f247f0a93f
|
||||
:END:
|
||||
#+title: APIM
|
||||
#+filetags: :docs:api:notes:career:
|
||||
|
||||
*Z notes on API management so I don’t forget*
|
||||
|
||||
1. API stands for application programming interface. It allows systems to communicate with each other.
|
||||
2. API management (or APIM) is the workstream that aims to provide a new technology platform for Microlise. It introduces a separate layer between customers and Microlise’s existing API products.
|
||||
|
||||
The core pillars:
|
||||
|
||||
[[./assets/career/Screenshot 2026-01-14 154800.png]]
|
||||
|
||||
The workflow of publishing API’s:
|
||||
|
||||
[[./assets/career/APIOps.png]]
|
||||
|
||||
This is summarised below:
|
||||
|
||||
1. When someone wants to create an API, they do so by creating a repo and a C# project. Ideally we should use the beautiful templates (https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Microlise.Templates).
|
||||
|
||||
2. When the engineer wants to deploy this API, it goes through a gated and main pipeline. Phase 2 of the main build will build the image using quay registry so it’s available there (quay.mms.local). The release will consume the artifact produced by the main pipeline and will push these endpoints into the Openshift server. Essentially it will pull the image from the quay registry, containerise it
|
||||
|
||||
Then publishing Api's into APIM (API management) using APIOps
|
||||
|
||||
1. The engineer will need to setup swagger build (docs explains how to do this)
|
||||
2. The engineer will create a PR for an API that has setup the APIOps pipeline (ie added the yaml pipeline and configured the variables - again, docs explain this in detail)
|
||||
3. There are two pipelines associated with this:
|
||||
- The gated build: [[https://azdo.microlise.com/MicroliseCollection/Microlise/_taskgroup/c85996c9-d9ae-40ff-bd60-94b60db541a9][Link (Gated)]]
|
||||
- The main build: [[https://azdo.microlise.com/MicroliseCollection/Microlise/_taskgroup/7bd21d7f-499b-487d-a0f7-2206ffdff841][Link (Main)]]
|
||||
- You will see that the term ~spec~ is used a lot. This is simply a json/yaml representation of your API interface (what you expose to the customer).
|
||||
- One of the gated tasks is linting, it uses the scripts in this directory to test the OpenAPI specification linting, see: [[https://azdo.microlise.com/MicroliseCollection/Microlise/_git/ApiManagement.Pipeline.AgentScripts][Link]].
|
||||
4. Another task adds API Governance Council as reviewers if there are OpenAPI Specification changes. All this can be viewed in the task group (see point a).
|
||||
5. Once the main build passes, it triggers an ApiOps pipeline (defined in step 2), which creates a PR in the APIOps repository ([[https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Microlise.APIOps][Link]])
|
||||
6. Once this PR is reviewed and approved by the Api GC, the Publish pipeline is triggered ([[https://azdo.microlise.com/MicroliseCollection/Microlise/_build?definitionId=1686&_a=summary][Link]]) which does a 2 way sync so that the APIM environments are in line with the OpenAPI specs. The publisher pipeline runs upto the CERT environment only, the PROD requires approval.
|
||||
|
||||
There are two openshift clusters, one is gen and one is prod. Anything not prod goes into gen, and no one can access the prod cluster besides Openshift itself so test well.
|
||||
|
||||
The link to the sharepoint site:
|
||||
- [[https://microliseuk.sharepoint.com/sites/SoftwareEngineering/SitePages/API-Management.aspx?source=https%3A%2F%2Fmicroliseuk.sharepoint.com%2Fsites%2FSoftwareEngineering%2FSitePages%2FForms%2FByAuthor.aspx][Api management sharepoint]]
|
||||
|
||||
Link to the onboarding doc:
|
||||
- [[https://microliseuk.sharepoint.com/:w:/r/sites/SoftwareEngineering/_layouts/15/Doc.aspx?sourcedoc=%7BCF78DE96-7CC0-482A-9A66-647771CB8A04%7D&file=APIOpsOnboardingDocumentation.docx&action=default&mobileredirect=true][Onboarding Doc]]
|
||||
|
||||
The link to the API management API gateway release:
|
||||
- [[https://azdo.microlise.com/MicroliseCollection/Microlise/_release?_a=releases&view=mine&definitionId=71][Link]]
|
||||
|
||||
Reverse proxy:
|
||||
- [[https://azdo.microlise.com/MicroliseCollection/Microlise/_build?definitionId=2439&_a=summary][Pipeline]]
|
||||
- [[https://microliseuk.sharepoint.com/sites/SoftwareEngineering/SitePages/Support-Guide---APIM-Reverse-Proxy.aspx][Sharepoint]]
|
||||
|
||||
Read up on:
|
||||
- Quick Start Kubernetes (nigel Poulton)
|
||||
- How is openshift different from k8? ([[https://microliseuk.sharepoint.com/sites/StorageCompute/ContainerPlatformUsers/SitePages/How-is-OpenShift-different-from-Kubernetes.aspx][Link]])
|
||||
544
Career Concepts/20260121173318-api_architecture.org
Normal file
544
Career Concepts/20260121173318-api_architecture.org
Normal file
@@ -0,0 +1,544 @@
|
||||
:PROPERTIES:
|
||||
:ID: 49b195c8-e116-40ca-86e8-62c65dbb5a4f
|
||||
:END:
|
||||
#+title: API Architecture
|
||||
#+filetags: :notes:concepts:api:
|
||||
#+category: Career Concepts
|
||||
|
||||
*Z notes on API architecture - companion to [[id:56fabaf6-e8aa-45d0-a1c1-89f247f0a93f][APIM notes]]*
|
||||
|
||||
* 1. What is API Architecture?
|
||||
|
||||
API architecture is the set of rules, patterns, and structural decisions that govern how APIs are designed, exposed, consumed, and maintained across a system. It sits above individual API implementation - it's about *how APIs fit together* as a platform.
|
||||
|
||||
In Microlise's context: the APIOps pipeline, the APIM gateway layer, OpenShift clusters, and the OpenAPI specs are all artefacts *of* an architectural decision. Understanding the architecture behind them makes the pipeline choices make sense.
|
||||
|
||||
* 2. Architectural Styles
|
||||
|
||||
Different styles define how clients and servers communicate. These are not mutually exclusive - a platform can expose multiple styles simultaneously (e.g. REST externally, gRPC internally).
|
||||
|
||||
** 2.1 REST (Representational State Transfer)
|
||||
|
||||
The dominant style for public and partner APIs. Key constraints:
|
||||
|
||||
- *Stateless*: Each request must contain all the context needed to fulfil it. No session state is stored server-side between calls.
|
||||
- *Resource-oriented*: APIs are modelled around nouns (resources), not verbs (actions).
|
||||
- Good: ~GET /vehicles/{id}~
|
||||
- Bad: ~POST /getVehicle~
|
||||
- *Uniform interface*: Standard HTTP verbs carry semantic meaning:
|
||||
| Verb | Meaning |
|
||||
|--------+--------------------------------|
|
||||
| GET | Read a resource |
|
||||
| POST | Create a resource |
|
||||
| PUT | Replace a resource entirely |
|
||||
| PATCH | Partially update a resource |
|
||||
| DELETE | Remove a resource |
|
||||
- *Layered system*: Clients don't know if they're talking to the real backend or a gateway/proxy/cache. This is exactly what Microlise's APIM layer provides.
|
||||
- *Cacheable*: Responses should declare whether they can be cached, enabling CDN and client-side optimisation.
|
||||
|
||||
OpenAPI Specification (OAS/Swagger) is the standard way to *describe* a REST API. The ~spec~ referred to throughout the APIOps pipeline is this document.
|
||||
|
||||
** 2.2 GraphQL
|
||||
|
||||
A query language for APIs developed by Meta. Instead of fixed endpoints, clients send a query describing exactly what data they need.
|
||||
|
||||
- Single endpoint: ~POST /graphql~
|
||||
- Client drives the shape of the response - no over-fetching or under-fetching.
|
||||
- Good for: complex, interconnected data models; front-end teams who iterate quickly.
|
||||
- Trade-off: harder to cache, more complex server-side resolver logic, linting/governance is less mature than OAS.
|
||||
|
||||
Not currently the Microlise APIM pattern but worth understanding as a contrast.
|
||||
|
||||
** 2.3 gRPC (Google Remote Procedure Call)
|
||||
|
||||
Uses Protocol Buffers (protobuf) as the interface definition language and HTTP/2 as transport.
|
||||
|
||||
- Strongly typed contracts defined in ~.proto~ files.
|
||||
- Extremely high performance - binary serialisation, multiplexed streams.
|
||||
- Ideal for: internal service-to-service calls, microservices, high-throughput scenarios.
|
||||
- Trade-off: not human-readable, harder to test with standard tooling (curl, Postman), less browser-friendly.
|
||||
|
||||
Think of gRPC as what might live *behind* an API gateway - internal communication between microservices - while REST/OAS faces outward toward customers.
|
||||
|
||||
** 2.4 AsyncAPI / Event-Driven APIs
|
||||
|
||||
Not all APIs are request-response. Event-driven APIs use messaging patterns:
|
||||
|
||||
- *Webhooks*: Server POSTs to a client-registered URL when an event occurs.
|
||||
- *WebSockets*: Persistent bi-directional connection between client and server.
|
||||
- *Server-Sent Events (SSE)*: One-way stream from server to client.
|
||||
- *Message queues* (Kafka, RabbitMQ, Azure Service Bus): Decoupled async messaging.
|
||||
|
||||
AsyncAPI is the OAS equivalent for event-driven interfaces - a specification format for documenting these contracts.
|
||||
|
||||
* 3. API Gateway Pattern
|
||||
|
||||
This is the core of what APIM implements. An API gateway sits as an intermediary between consumers (customers, internal teams) and backend services.
|
||||
|
||||
#+begin_src mermaid
|
||||
flowchart TD
|
||||
EC[External Consumer]
|
||||
GW["API Gateway / APIM
|
||||
────────────────────
|
||||
Auth · Rate Limiting
|
||||
Transforms · Routing
|
||||
Logging · Caching"]
|
||||
SA["Service A\n(OpenShift)"]
|
||||
SB["Service B\n(OpenShift)"]
|
||||
SC["Service C\n(OpenShift)"]
|
||||
|
||||
EC --> GW
|
||||
GW --> SA
|
||||
GW --> SB
|
||||
GW --> SC
|
||||
#+end_src
|
||||
|
||||
** 3.1 What the gateway does
|
||||
|
||||
| Concern | What it means |
|
||||
|--------------------------+-------------------------------------------------------------------------------|
|
||||
| *Authentication* | Verifies who the caller is (OAuth2 tokens, API keys, mutual TLS) |
|
||||
| *Authorisation* | Determines what the caller is allowed to do (scopes, claims) |
|
||||
| *Rate limiting* | Caps requests per second/minute/hour per consumer or globally |
|
||||
| *Throttling* | Gracefully slows or queues excess requests rather than rejecting them |
|
||||
| *Request transformation* | Rewrites headers, payloads, or paths before forwarding to backends |
|
||||
| *Response transformation*| Strips internal fields, reformats responses for the consumer contract |
|
||||
| *Routing* | Directs traffic to the correct backend based on path, headers, or content |
|
||||
| *Load balancing* | Distributes traffic across backend instances |
|
||||
| *Caching* | Stores responses to reduce backend load for idempotent requests |
|
||||
| *Observability* | Centralises access logs, metrics, and tracing across all APIs |
|
||||
|
||||
In Azure APIM specifically, these concerns are implemented as *policies* - XML-based declarative rules that run at gateway level.
|
||||
|
||||
** 3.2 Reverse Proxy vs API Gateway
|
||||
|
||||
The Microlise notes reference a Reverse Proxy pipeline alongside APIM. These are related but distinct:
|
||||
|
||||
| Aspect | Reverse Proxy | API Gateway |
|
||||
|-------------------+-------------------------------------------+--------------------------------------------------|
|
||||
| Primary purpose | Routing and TLS termination | Full API lifecycle management |
|
||||
| Protocol awareness| Layer 4/7 (TCP/HTTP) | Layer 7, API-aware (understands REST, OAS) |
|
||||
| Policy engine | Minimal (Nginx/HAProxy config) | Rich (auth, transforms, quotas, subscriptions) |
|
||||
| Developer portal | No | Yes - consumer-facing API catalogue |
|
||||
| Examples | Nginx, HAProxy, Traefik | Azure APIM, Kong, AWS API Gateway |
|
||||
|
||||
A common pattern (and likely what Microlise uses) is: Reverse proxy handles ingress and TLS termination → traffic forwarded to APIM for policy enforcement → APIM routes to OpenShift services.
|
||||
|
||||
* 4. API Design Principles
|
||||
|
||||
** 4.1 Contract-First Design
|
||||
|
||||
Define the OpenAPI spec *before* writing implementation code. The spec is the source of truth.
|
||||
|
||||
Benefits:
|
||||
- Frontend/consumer teams can mock and build against the spec immediately.
|
||||
- Linting pipelines (like the one in APIOps gated build) can enforce governance before any code ships.
|
||||
- Breaking change detection is automated.
|
||||
|
||||
The APIOps pipeline enforces this: the spec is committed to source control, linted, reviewed by the API Governance Council, and only then does the publish pipeline sync it to APIM environments.
|
||||
|
||||
** 4.2 Versioning Strategies
|
||||
|
||||
APIs evolve. Versioning prevents changes from breaking existing consumers.
|
||||
|
||||
| Strategy | Example | Trade-offs |
|
||||
|---------------------+---------------------------------------+-----------------------------------------------------|
|
||||
| *URI versioning* | ~/v1/vehicles~, ~/v2/vehicles~ | Explicit, cacheable, easy to route. Pollutes paths. |
|
||||
| *Header versioning* | ~Accept: application/vnd.api.v2+json~ | Clean URIs. Harder to test, less cache-friendly. |
|
||||
| *Query param* | ~/vehicles?version=2~ | Simple but considered poor practice for REST. |
|
||||
|
||||
URI versioning is the most common and is what Azure APIM handles well via routing rules.
|
||||
|
||||
** 4.3 Breaking vs Non-Breaking Changes
|
||||
|
||||
Knowing what constitutes a breaking change is critical for API governance (i.e. why the API GC reviews spec PRs).
|
||||
|
||||
| *Non-breaking (additive)* | *Breaking* |
|
||||
|----------------------------------------+--------------------------------------------------|
|
||||
| Adding a new optional field to response | Removing or renaming a field |
|
||||
| Adding a new endpoint | Changing a field's type |
|
||||
| Adding a new optional query parameter | Making an optional parameter required |
|
||||
| New enum value (with caution) | Changing HTTP status codes for existing scenarios|
|
||||
| | Changing authentication schemes |
|
||||
|
||||
** 4.4 Resource Naming Conventions
|
||||
|
||||
- Use *nouns*, not verbs: ~/journeys~ not ~/getJourneys~
|
||||
- Use *plural* for collections: ~/vehicles~ not ~/vehicle~
|
||||
- Use *kebab-case* for multi-word: ~/driver-events~ not ~/driverEvents~
|
||||
- Nest to show ownership, but limit depth: ~/vehicles/{id}/journeys~ is fine; ~/vehicles/{id}/journeys/{jid}/events/{eid}/metadata~ is not.
|
||||
- Never expose internal implementation details in paths (~/{internalDatabaseId}~ leaks schema).
|
||||
|
||||
** 4.5 HTTP Status Codes
|
||||
|
||||
Correct status codes are part of the API contract. Misuse breaks consumers who rely on them.
|
||||
|
||||
| Code | Meaning | When to use |
|
||||
|------+-------------------------------+----------------------------------------------------|
|
||||
| 200 | OK | Successful GET, PUT, PATCH |
|
||||
| 201 | Created | Successful POST that created a resource |
|
||||
| 204 | No Content | Successful DELETE or action with no response body |
|
||||
| 400 | Bad Request | Client sent malformed/invalid data |
|
||||
| 401 | Unauthorized | Not authenticated (no or invalid token) |
|
||||
| 403 | Forbidden | Authenticated but not authorised for this resource |
|
||||
| 404 | Not Found | Resource does not exist |
|
||||
| 409 | Conflict | State conflict (duplicate, version mismatch) |
|
||||
| 422 | Unprocessable Entity | Semantically invalid (e.g. invalid date range) |
|
||||
| 429 | Too Many Requests | Rate limit exceeded |
|
||||
| 500 | Internal Server Error | Unhandled server-side failure |
|
||||
| 503 | Service Unavailable | Downstream dependency down, circuit breaker open |
|
||||
|
||||
* 5. API Security Architecture
|
||||
|
||||
** 5.1 Authentication Patterns
|
||||
|
||||
| Pattern | How it works | Typical use |
|
||||
|------------------+------------------------------------------------------------+------------------------------------------|
|
||||
| *API Keys* | Static key passed in header (~x-api-key~) or query param | Simple, internal/partner APIs |
|
||||
| *OAuth 2.0* | Token-based; client obtains a bearer token from auth server| Public APIs, delegated access |
|
||||
| *OpenID Connect* | OAuth 2.0 + identity layer (ID tokens, user info endpoint) | APIs that need to know *who* the user is |
|
||||
| *Mutual TLS* | Both client and server present certificates | High-security service-to-service |
|
||||
| *JWT* | Signed token carrying claims; verified without calling auth server | Stateless auth at gateway level |
|
||||
|
||||
Azure APIM supports all of these via policies. A common pattern: APIM validates the JWT at the gateway before the request ever reaches an OpenShift pod.
|
||||
|
||||
** 5.2 OAuth 2.0 Grant Types
|
||||
|
||||
| Grant type | Use case |
|
||||
|-------------------------+----------------------------------------------------------------|
|
||||
| *Client Credentials* | Machine-to-machine (no user involved). Most common for APIs. |
|
||||
| *Authorization Code* | User-facing apps; user logs in and delegates access |
|
||||
| *Authorization Code + PKCE* | Same as above but for SPAs/mobile (no client secret) |
|
||||
| *Implicit* (deprecated) | Was used for SPAs - replaced by Auth Code + PKCE |
|
||||
|
||||
** 5.3 Zero Trust at the API Layer
|
||||
|
||||
Zero Trust means: *never trust, always verify* - even internal services must authenticate.
|
||||
|
||||
Principles applied to APIs:
|
||||
- Every service-to-service call requires a valid token (no implicit trust on the internal network).
|
||||
- Tokens have minimum required scopes (principle of least privilege).
|
||||
- mTLS between internal services adds a second layer even if a token is compromised.
|
||||
- All traffic - internal and external - goes through the gateway and is logged.
|
||||
|
||||
* 6. API Lifecycle Management
|
||||
|
||||
This maps directly to the APIOps workflow in the APIM notes.
|
||||
|
||||
#+begin_src mermaid
|
||||
flowchart LR
|
||||
Design[Design]
|
||||
Develop[Develop]
|
||||
Test[Test]
|
||||
Publish[Publish]
|
||||
Monitor[Monitor]
|
||||
Retire[Retire]
|
||||
|
||||
Design --> Develop --> Test --> Publish --> Monitor --> Retire
|
||||
|
||||
Design -.-> D1["OAS Spec\nContract First"]
|
||||
Develop -.-> D2["C# Project\nTemplates\nOpenShift"]
|
||||
Test -.-> D3["Gated Build\nPipeline\nLinting + API GC"]
|
||||
Publish -.-> D4["APIM Publish\nPipeline\nDev → Cert → Prod"]
|
||||
Monitor -.-> D5["Analytics\nDashboards\nAPIM Portal"]
|
||||
Retire -.-> D6["Deprecation\nNotices\nVersion Sunset"]
|
||||
#+end_src
|
||||
|
||||
** 6.1 API Governance
|
||||
|
||||
The API Governance Council (API GC) referenced in the notes is the enforcement body for architectural standards. Common governance concerns:
|
||||
|
||||
- *Linting*: Automated rules against the OAS spec. The APIOps pipeline uses scripts from ~ApiManagement.Pipeline.AgentScripts~ to enforce this.
|
||||
- *Review gates*: No spec change merges without GC approval - prevents inconsistent or insecure APIs reaching production.
|
||||
- *Naming standards*: Enforced in the spec review (see §4.4).
|
||||
- *Breaking change policy*: Defines how long old versions must be supported before retirement.
|
||||
- *Security policy*: All APIs must use approved auth methods; no unauthenticated endpoints in production.
|
||||
|
||||
** 6.2 APIOps (GitOps for APIs)
|
||||
|
||||
APIOps applies GitOps principles to API management: the APIM configuration is stored as code in a Git repository and the pipeline is the only mechanism that changes APIM state.
|
||||
|
||||
Key properties:
|
||||
- *Declarative*: The ~Microlise.APIOps~ repo describes the desired state of all APIs in APIM.
|
||||
- *Versioned*: Every change is a PR - full audit trail.
|
||||
- *Automated*: The publish pipeline does the two-way sync; no manual APIM portal edits.
|
||||
- *Environment promotion*: Changes flow Dev -> Cert -> Prod, with a manual approval gate before Prod.
|
||||
|
||||
This is analogous to how Terraform or Helm work for infrastructure - the repo *is* the truth.
|
||||
|
||||
* 7. API Observability
|
||||
|
||||
An often-overlooked architectural concern. APIs you can't observe are APIs you can't operate.
|
||||
|
||||
** 7.1 The Three Pillars
|
||||
|
||||
| Pillar | What it captures | Tooling examples |
|
||||
|-----------+-------------------------------------------------------------+------------------------------------|
|
||||
| *Logs* | Discrete events: requests, responses, errors, auth failures | Azure Monitor, ELK, Splunk |
|
||||
| *Metrics* | Aggregated numbers over time: latency, error rate, RPS | Prometheus, Azure Metrics, Grafana |
|
||||
| *Traces* | End-to-end request journey across services | Jaeger, Zipkin, Azure App Insights |
|
||||
|
||||
** 7.2 Key API Metrics to Track
|
||||
|
||||
- *Latency*: p50, p95, p99 - not just average. Averages hide outliers.
|
||||
- *Error rate*: 5xx rate (server errors) and 4xx rate (client errors) separately.
|
||||
- *Throughput*: Requests per second - used to set rate limits and plan capacity.
|
||||
- *Availability*: Uptime percentage. SLAs are usually defined here (99.9% = ~8.7h downtime/year).
|
||||
- *Quota consumption*: How much of a consumer's rate limit are they using?
|
||||
|
||||
Azure APIM exposes all of these natively and can emit them to Azure Monitor.
|
||||
|
||||
** 7.3 Correlation IDs
|
||||
|
||||
Every request should carry a unique ~correlation-id~ (or ~x-request-id~) header. The gateway generates one if the client doesn't provide it and forwards it to all downstream services. This makes it possible to trace a single user request across multiple microservice logs.
|
||||
|
||||
#+begin_src mermaid
|
||||
flowchart LR
|
||||
C[Client]
|
||||
APIM["APIM\ngenerates correlation-id: abc-123"]
|
||||
SA["Service A logs\nabc-123 · vehicle lookup"]
|
||||
SB["Service B logs\nabc-123 · journey history"]
|
||||
|
||||
C --> APIM
|
||||
APIM --> SA
|
||||
SA --> SB
|
||||
#+end_src
|
||||
|
||||
* 8. Microservices & API Design
|
||||
|
||||
The OpenShift deployment model in Microlise's stack implies microservices. API architecture must account for how services communicate internally vs. externally.
|
||||
|
||||
** 8.1 Internal vs External APIs
|
||||
|
||||
| Aspect | Internal (East-West) | External (North-South) |
|
||||
|----------------+--------------------------------------------+----------------------------------------------|
|
||||
| Consumers | Other microservices | Customers, partners, third parties |
|
||||
| Protocol | gRPC, internal REST, message queues | REST over HTTPS via APIM |
|
||||
| Auth | mTLS, service accounts, internal tokens | OAuth2, API keys managed by APIM |
|
||||
| Discoverability| Service mesh / internal DNS | Developer portal in APIM |
|
||||
| Governance | Team-level conventions | API GC, formal versioning, SLA commitments |
|
||||
|
||||
** 8.2 API Aggregation / BFF Pattern
|
||||
|
||||
Backend for Frontend (BFF): a dedicated API layer tailored to a specific consumer (e.g. a mobile app, a portal). Instead of the consumer calling 5 microservices, a BFF aggregates them into a single call.
|
||||
|
||||
#+begin_src mermaid
|
||||
flowchart LR
|
||||
MA[Mobile App]
|
||||
BFF[BFF: Mobile API]
|
||||
VS[Vehicle Service]
|
||||
JS[Journey Service]
|
||||
DS[Driver Service]
|
||||
|
||||
MA --> BFF
|
||||
BFF --> VS
|
||||
BFF --> JS
|
||||
BFF --> DS
|
||||
#+end_src
|
||||
|
||||
APIM policies can implement lightweight aggregation, but for complex cases a dedicated BFF service is cleaner.
|
||||
|
||||
** 8.3 Service Mesh (Complementary to API Gateway)
|
||||
|
||||
A service mesh (e.g. Istio, Linkerd) manages *internal* service-to-service communication within OpenShift/Kubernetes:
|
||||
|
||||
- mTLS between pods automatically.
|
||||
- Traffic policies (retries, circuit breaking) at the network level.
|
||||
- Observability (traces, metrics) without code changes.
|
||||
|
||||
The API Gateway handles North-South (external) traffic; the service mesh handles East-West (internal). They are complementary, not competing.
|
||||
|
||||
* 9. API Design Patterns
|
||||
|
||||
** 9.1 Pagination
|
||||
|
||||
Never return unbounded collections. Standard patterns:
|
||||
|
||||
- *Offset/limit*: ~GET /journeys?offset=0&limit=50~. Simple but inefficient at high offsets.
|
||||
- *Cursor-based*: ~GET /journeys?cursor=eyJpZCI6MTAwfQ==~. Efficient for large datasets; the cursor encodes the last seen position.
|
||||
- *Page-based*: ~GET /journeys?page=3&pageSize=50~. User-friendly but shares offset's inefficiency.
|
||||
|
||||
Response should include metadata:
|
||||
#+BEGIN_SRC json
|
||||
{
|
||||
"data": [...],
|
||||
"pagination": {
|
||||
"total": 1420,
|
||||
"limit": 50,
|
||||
"nextCursor": "eyJpZCI6MTUwfQ=="
|
||||
}
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
** 9.2 Filtering, Sorting, and Field Selection
|
||||
|
||||
- Filtering: ~GET /vehicles?status=active&driverType=HGV~
|
||||
- Sorting: ~GET /journeys?sort=-startedAt~ (prefix ~-~ for descending)
|
||||
- Field selection (sparse fieldsets): ~GET /vehicles?fields=id,registration,status~ - reduces payload size.
|
||||
|
||||
** 9.3 Idempotency
|
||||
|
||||
A request is idempotent if making it multiple times produces the same result as making it once. Crucial for retry logic.
|
||||
|
||||
| Method | Idempotent? | Safe (no side effects)? |
|
||||
|--------+-------------+-------------------------|
|
||||
| GET | Yes | Yes |
|
||||
| PUT | Yes | No |
|
||||
| DELETE | Yes | No |
|
||||
| POST | No | No |
|
||||
| PATCH | No* | No |
|
||||
|
||||
*PATCH can be designed to be idempotent but isn't by definition.
|
||||
|
||||
For non-idempotent operations (POST), use an ~Idempotency-Key~ header. The server stores the result keyed to that value; duplicate requests return the cached result rather than processing again.
|
||||
|
||||
** 9.4 HATEOAS
|
||||
|
||||
Hypermedia as the Engine of Application State - responses include links to related actions:
|
||||
|
||||
#+BEGIN_SRC json
|
||||
{
|
||||
"id": "v-123",
|
||||
"registration": "AB12 CDE",
|
||||
"_links": {
|
||||
"self": { "href": "/vehicles/v-123" },
|
||||
"journeys": { "href": "/vehicles/v-123/journeys" },
|
||||
"driver": { "href": "/drivers/d-456" }
|
||||
}
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
Rarely implemented fully in practice but worth understanding as the most complete expression of REST.
|
||||
|
||||
* 10. OpenAPI Specification Deep Dive
|
||||
|
||||
Since OAS is central to the APIOps pipeline, understanding its structure is practical knowledge.
|
||||
|
||||
#+BEGIN_SRC yaml
|
||||
openapi: "3.1.0"
|
||||
info:
|
||||
title: Vehicle Service API
|
||||
version: "2.0.0"
|
||||
description: Manages vehicle records for the Microlise platform.
|
||||
|
||||
servers:
|
||||
- url: https://api.microlise.com/v2
|
||||
description: Production
|
||||
|
||||
paths:
|
||||
/vehicles/{vehicleId}:
|
||||
get:
|
||||
summary: Get a vehicle by ID
|
||||
operationId: getVehicleById # Unique identifier used in code gen
|
||||
tags: [Vehicles]
|
||||
parameters:
|
||||
- name: vehicleId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
"200":
|
||||
description: Vehicle found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Vehicle"
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
|
||||
components:
|
||||
schemas:
|
||||
Vehicle:
|
||||
type: object
|
||||
required: [id, registration]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
registration:
|
||||
type: string
|
||||
example: "AB12 CDE"
|
||||
status:
|
||||
type: string
|
||||
enum: [active, inactive, maintenance]
|
||||
|
||||
responses:
|
||||
NotFound:
|
||||
description: Resource not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ProblemDetails"
|
||||
|
||||
securitySchemes:
|
||||
oauth2:
|
||||
type: oauth2
|
||||
flows:
|
||||
clientCredentials:
|
||||
tokenUrl: https://auth.microlise.com/oauth2/token
|
||||
scopes:
|
||||
vehicles:read: Read vehicle data
|
||||
vehicles:write: Create and update vehicles
|
||||
|
||||
security:
|
||||
- oauth2: [vehicles:read]
|
||||
#+END_SRC
|
||||
|
||||
Key OAS concepts:
|
||||
- ~operationId~: Used by code generators and APIM to reference operations in policies.
|
||||
- ~$ref~: DRY principle - define schemas and responses once, reuse everywhere.
|
||||
- ~components~: The library section - schemas, parameters, responses, security schemes.
|
||||
- ~tags~: Grouping for the developer portal - consumers see organised API docs.
|
||||
- ~security~: Applied globally here; can be overridden per-operation.
|
||||
|
||||
* 11. Connecting the Dots: Microlise Architecture Map
|
||||
|
||||
Mapping the APIM notes to the architectural concepts above:
|
||||
|
||||
| APIM Note Item | Architectural Concept |
|
||||
|--------------------------------------------+-------------------------------------------------------|
|
||||
| Separate layer between customers & APIs | API Gateway Pattern (§3) |
|
||||
| OpenAPI spec / swagger build | Contract-First Design (§4.1), OAS (§10) |
|
||||
| APIOps pipeline, spec in git | APIOps / GitOps for APIs (§6.2) |
|
||||
| API Governance Council review | API Governance (§6.1), Breaking Changes (§4.3) |
|
||||
| Linting scripts (~AgentScripts~) | Automated governance enforcement |
|
||||
| Gated + main pipeline | CI/CD gates for quality and security |
|
||||
| Two-way sync, publish pipeline | Declarative state management (APIOps) |
|
||||
| Dev -> Cert -> Prod with approval gate | Environment promotion pattern (§6.2) |
|
||||
| Gen cluster vs Prod cluster | Environment isolation, blast radius reduction |
|
||||
| Reverse proxy pipeline | Reverse Proxy vs API Gateway (§3.2) |
|
||||
| Quay registry, OpenShift containers | Microservices deployment, East-West traffic (§8.1) |
|
||||
| Swagger/OAS spec as PR artefact | Spec-as-code, version-controlled contracts |
|
||||
|
||||
* 12. Further Reading & Reference
|
||||
|
||||
** Recommended (from APIM notes)
|
||||
|
||||
- Quick Start Kubernetes - Nigel Poulton ([[https://microliseuk.sharepoint.com/sites/StorageCompute/ContainerPlatformUsers/SitePages/How-is-OpenShift-different-from-Kubernetes.aspx][OpenShift vs K8s]])
|
||||
|
||||
** Additional Architecture Resources
|
||||
|
||||
- [[https://spec.openapis.org/oas/v3.1.0][OpenAPI Specification 3.1.0 (official)]]
|
||||
- [[https://www.asyncapi.com/docs][AsyncAPI Documentation]]
|
||||
- [[https://grpc.io/docs/][gRPC Official Docs]]
|
||||
- [[https://learn.microsoft.com/en-us/azure/api-management/][Azure API Management Docs]]
|
||||
- [[https://microservices.io/patterns/apigateway.html][Microservices.io - API Gateway Pattern]]
|
||||
- [[https://oauth.net/2/][OAuth 2.0 (oauth.net)]]
|
||||
- [[https://swagger.io/specification/][Swagger / OAS Reference]]
|
||||
|
||||
** Key Terms Glossary
|
||||
|
||||
| Term | Definition |
|
||||
|----------------+------------------------------------------------------------------------------|
|
||||
| OAS / Swagger | OpenAPI Specification - a standard format for describing REST APIs |
|
||||
| APIOps | Applying GitOps principles to API management (spec-as-code, pipeline-driven) |
|
||||
| APIM | API Management - the platform/layer that governs API lifecycle |
|
||||
| Gateway | Intermediary that enforces policy (auth, rate limiting, routing) for APIs |
|
||||
| Spec | Short for specification - the OAS JSON/YAML document describing an API |
|
||||
| Idempotency | Property where repeating a request has the same effect as making it once |
|
||||
| mTLS | Mutual TLS - both parties in a connection authenticate with certificates |
|
||||
| BFF | Backend for Frontend - an API tailored to a specific consumer's needs |
|
||||
| Service Mesh | Infrastructure layer managing internal service-to-service communication |
|
||||
| Breaking Change| An API change that requires existing consumers to update their integration |
|
||||
600
Career Concepts/20260305102210-cicd_example.org
Normal file
600
Career Concepts/20260305102210-cicd_example.org
Normal file
@@ -0,0 +1,600 @@
|
||||
:PROPERTIES:
|
||||
:ID: 2767b5ac-f2c9-4b1e-ab87-82c43cdec4c1
|
||||
:END:
|
||||
#+title: CI/CD Example
|
||||
#+category: Career Concepts
|
||||
|
||||
During the first wave in 2026, we planned to get the netcore version of site visits out to customers. There were a bunch of tasks relating to this, so I asked AI to conceptually explain them.
|
||||
|
||||
* Prompt:
|
||||
|
||||
I want to understand builds and pipelines in more depth. we have a set of tasks to get a new upgraded project to customers. this is task 1:
|
||||
|
||||
Add the .net core version to the TMC release pipeline.
|
||||
Follow this guide so that the build artifacts are included in the TMC release
|
||||
|
||||
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Documents?path=/TMC/Deployment/AddingANewProjectToTMC.md&_a=preview
|
||||
|
||||
(This will add the artifact to the release, you will then need to test this locally, see the other task)
|
||||
|
||||
After that, we need to make the below changes as we did for the DriverWebAPI:
|
||||
|
||||
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/TMC_Release/pullrequest/23129?path=/ReleasePackagesConfig.csv&_a=files
|
||||
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment/pullrequest/23154?_a=files
|
||||
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/TMCBranchTool/pullrequest/23766?_a=files
|
||||
|
||||
this is task 2:
|
||||
Add application file and make deployable locally
|
||||
See this PR from when we previously did on Drivers: https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/pullrequest/23188?path=/manifests/customers/dev/LocalDeploy/DEV/_apps.yml
|
||||
|
||||
Note: That some of the properties in the files are different to what you have for a local deploy, if in doubt refer to main to ensure that we have no consistencies.
|
||||
|
||||
Also, we don't need to alter the connection string as this has already been done.
|
||||
|
||||
====
|
||||
|
||||
This requires the previous tasks to be completed (main build and artifact added to release)
|
||||
|
||||
Follow this commit as an example
|
||||
|
||||
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/commit/aeb2dbf1bbcef1b672aee05fdc7988959afd1a36?refName=refs/heads/main
|
||||
|
||||
Create a new application file for the dotnet core version of the service, swap it out in the manifests for the local deploy along with any relevant configuration
|
||||
|
||||
There may be some differences due to this being a web api rather than a background service, and the fact that we use the appsettings.json rather than the app.config - in which case look to Arrivals and departures and vehiclev2 if that is still around
|
||||
|
||||
Set up local TMC and deploy - make sure it works as expected
|
||||
|
||||
This is now possible on the new domain joined machines with a VM - did it myself and it works well
|
||||
|
||||
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Documents?path=/TMC/Deployment/Local%20Deployment%20and%20running%20ATFs%20on%20non-domain%20joined%20machines.md&_a=preview
|
||||
|
||||
this is 3:
|
||||
Make deployable in QA (Toblerone)
|
||||
Check out this commit for the AVL where the new service was added to the templates and the deploy file, use what was learned from the local deploy to ensure this works in the same way
|
||||
|
||||
Check if you can just apply this to the toblerone box, the deploy_all.yml file governs what is actually deployed, this might not be possible but worth a check
|
||||
|
||||
Test that Toblerone deploys okay
|
||||
|
||||
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/commit/59db355dbb80c784d7b7ca9f3bb30fc00ef1d13e?refName=refs/heads/main&path=/manifests
|
||||
|
||||
See this PR for how we did it last time for the Driver Web API: https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/pullrequest/23320
|
||||
|
||||
This needs to be changed for the current release, potentially the previous release if it errors when that happens as well as the ad hoc. See the last three files in the above PR.
|
||||
|
||||
task 4:
|
||||
Add artifact to the ad-hoc pipelines for QA / Cert
|
||||
Need to complete the previous Toblerone QA task first!
|
||||
|
||||
We need to add a similar artifact for SiteVisits to the ad hoc QA / Cert release pipeline like so:
|
||||
|
||||
Image
|
||||
|
||||
And then give it a run and make sure it works.
|
||||
|
||||
See the release pipeline here: TMC.SiteVisitsWebApi - Pipelines
|
||||
|
||||
task 5:
|
||||
Ensure that you test each endpoint with different data, ensuring the experience is exactly the same for each endpoint (auth, request / response)
|
||||
|
||||
As we are planning to hotswap the instances over, they must work exactly the same
|
||||
|
||||
Make sure its on the same URL
|
||||
|
||||
task 6:
|
||||
Make deployable in the rest of QA
|
||||
We have this running in Toblerone QA, once we are happy with the API in Toblerone we need to roll it out to the rest of QA.
|
||||
|
||||
Aaron also suggested considering doing the internal CERT environments at this stage, then we have a more live like environment tested early on too.
|
||||
|
||||
See this PR for how we did this for the Driver Web API: https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/pullrequest/24329?path=/manifests/TemplateFiles/26.1/QA/deploy_tmc.yml
|
||||
|
||||
task 7:
|
||||
Ensure that the new Serilog logs are captured into elastic
|
||||
This file needs updating with the paths for the serilogs in the sitevisitswebapi
|
||||
|
||||
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/ELK-Beats?path=/inventories/uat_web_servers/templates/filebeat~planBstructuredLogs.yml
|
||||
|
||||
However it does not look like servicename and customername parsing is working for the existing logs
|
||||
|
||||
Effectively, add a line like this but for our SiteVisits API:
|
||||
|
||||
Image
|
||||
|
||||
task 8:
|
||||
Make deployable in UAT
|
||||
Update UAT to use the new dotnet core version of the API, use what was learned from the local deploy to ensure this works in the same way
|
||||
|
||||
Use this commit for reference
|
||||
|
||||
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/commit/2fce44462b699b88e4c2597c8492a1a0dad1614d?refName=refs/heads/main
|
||||
|
||||
See this PR for what we did last time for UAT (incorporates other environments): https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/pullrequest/25631?path=/manifests/TemplateFiles/26.2/UAT/deploy_all_zero_predeploy.yml
|
||||
|
||||
task 9:
|
||||
Make deployable in live
|
||||
Update live to use the new dotnet core version of the API, use what was learned from the local deploy to ensure this works in the same way
|
||||
|
||||
Use this commit for reference
|
||||
|
||||
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/commit/ce61205a1f53649e7b1313fb78eb72225d99503d?refName=refs/heads/main&path=/manifests/customers/prod/CEVA_BAXTER/LIVE/_customer.yml
|
||||
|
||||
See this PR for what we did last time for live (incorporates other environments): https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/pullrequest/25631?path=/manifests/TemplateFiles/26.2/UAT/deploy_all_zero_predeploy.yml
|
||||
|
||||
|
||||
* Response
|
||||
|
||||
You’re essentially looking at a **full CI/CD path** for introducing a **new version of a service (.NET Core API)** into a large enterprise deployment system. The tasks look complicated because they touch **multiple layers of the delivery pipeline**, not just code.
|
||||
|
||||
I'll explain this in a **mental model first**, then walk through **what each task is really doing in the pipeline**.
|
||||
|
||||
---
|
||||
|
||||
** 1. The Big Picture: What a Build & Release Pipeline Is
|
||||
|
||||
In enterprise systems like Azure DevOps, deployment is usually split into two major stages.
|
||||
|
||||
1. Build Pipeline (CI)
|
||||
|
||||
Purpose: **Turn source code into deployable artifacts**
|
||||
|
||||
Steps typically include:
|
||||
|
||||
#+begin_src
|
||||
Code → Restore packages → Compile → Run tests → Package → Publish artifact
|
||||
#+end_src
|
||||
|
||||
Output = **artifact**
|
||||
|
||||
Example artifact:
|
||||
|
||||
#+begin_src
|
||||
SiteVisitsWebApi.zip
|
||||
#+end_src
|
||||
|
||||
This artifact contains:
|
||||
|
||||
#+begin_src
|
||||
dlls
|
||||
configs
|
||||
dependencies
|
||||
startup files
|
||||
#+end_src
|
||||
|
||||
Think of an **artifact** as a **versioned package of your application**.
|
||||
|
||||
|
||||
2. Release Pipeline (CD)
|
||||
|
||||
Purpose: **Take the artifact and deploy it to environments**
|
||||
|
||||
Example environments:
|
||||
|
||||
#+begin_src
|
||||
Local
|
||||
QA
|
||||
CERT
|
||||
UAT
|
||||
LIVE
|
||||
#+end_src
|
||||
|
||||
Each environment might have:
|
||||
- different configs
|
||||
- different servers
|
||||
- different manifests
|
||||
|
||||
|
||||
*Your System Specifically*
|
||||
|
||||
You are working with something like:
|
||||
|
||||
#+begin_src
|
||||
|
||||
|
||||
Git Repo
|
||||
↓
|
||||
Build Pipeline
|
||||
↓
|
||||
Artifacts
|
||||
↓
|
||||
TMC Release Pipeline
|
||||
↓
|
||||
Deployment Manifests
|
||||
↓
|
||||
Servers
|
||||
|
||||
#+end_src
|
||||
|
||||
|
||||
** 2. Why This Task Exists
|
||||
|
||||
You are **introducing a new .NET Core version of an API**.
|
||||
|
||||
Previously there was likely:
|
||||
|
||||
#+begin_src
|
||||
SiteVisitsWebApi (.NET Framework)
|
||||
#+end_src
|
||||
|
||||
Now:
|
||||
|
||||
#+begin_src
|
||||
SiteVisitsWebApi (.NET Core)
|
||||
#+end_src
|
||||
|
||||
|
||||
So you must:
|
||||
|
||||
1. Build it
|
||||
2. Package it
|
||||
3. Add it to release pipeline
|
||||
4. Update deployment configs
|
||||
5. Deploy to environments gradually
|
||||
|
||||
|
||||
** 3. What Each Task Actually Means
|
||||
|
||||
I'll translate the tasks into **plain engineering intent**.
|
||||
|
||||
|
||||
|
||||
*** Task 1: Add .NET Core Version to Build + Release
|
||||
|
||||
What is happening?
|
||||
|
||||
You add the **new project to the build pipeline** so it produces an artifact.
|
||||
|
||||
Before:
|
||||
|
||||
~Build → DriverWebAPI artifact~
|
||||
|
||||
After:
|
||||
|
||||
#+begin_src
|
||||
|
||||
Build → DriverWebAPI artifact
|
||||
→ SiteVisitsWebApi artifact
|
||||
|
||||
#+end_src
|
||||
|
||||
|
||||
Why the PRs exist
|
||||
|
||||
These repositories control deployment:
|
||||
|
||||
#+begin_src
|
||||
TMC_Release
|
||||
Deployment
|
||||
TMCBranchTool
|
||||
#+end_src
|
||||
|
||||
They likely manage:
|
||||
|
||||
| Repo | Purpose |
|
||||
| ------------- | ------------------------- |
|
||||
| TMC_Release | release packaging |
|
||||
| Deployment | deployment scripts |
|
||||
| TMCBranchTool | release branch automation |
|
||||
|
||||
|
||||
What ReleasePackagesConfig.csv probably does
|
||||
|
||||
Something like:
|
||||
|
||||
#+begin_src
|
||||
|
||||
ServiceName,ArtifactName,DeploymentType
|
||||
DriverWebApi,DriverWebApi.zip,WebApi
|
||||
SiteVisitsWebApi,SiteVisitsWebApi.zip,WebApi
|
||||
|
||||
#+end_src
|
||||
|
||||
So the pipeline knows:
|
||||
|
||||
#+begin_src
|
||||
Include this artifact in the release bundle
|
||||
#+end_src
|
||||
|
||||
|
||||
Result of Task 1
|
||||
|
||||
Your pipeline will now produce:
|
||||
|
||||
Artifacts:
|
||||
|
||||
~DriverWebApi~
|
||||
|
||||
~SiteVisitsWebApi~
|
||||
|
||||
|
||||
And release pipeline can access them.
|
||||
|
||||
|
||||
|
||||
*** Task 2: Make Deployable Locally
|
||||
|
||||
Now you test deployment **without affecting real environments**.
|
||||
|
||||
This uses **deployment manifests**.
|
||||
|
||||
|
||||
What a manifest is
|
||||
|
||||
A manifest is basically a **deployment recipe**.
|
||||
|
||||
Example:
|
||||
|
||||
#+begin_src yaml
|
||||
|
||||
apps:
|
||||
- name: sitevisitswebapi
|
||||
artifact: SiteVisitsWebApi
|
||||
port: 5000
|
||||
config: appsettings.json
|
||||
|
||||
#+end_src
|
||||
|
||||
It tells the deployment system:
|
||||
|
||||
deploy this artifact
|
||||
with these configs
|
||||
to this environment
|
||||
|
||||
|
||||
What you do here
|
||||
|
||||
Create a new **application definition**.
|
||||
|
||||
Example:
|
||||
|
||||
~_apps.yml~
|
||||
|
||||
Add:
|
||||
|
||||
~sitevisitswebapi~
|
||||
|
||||
Then configure:
|
||||
|
||||
#+begin_src
|
||||
artifact source
|
||||
ports
|
||||
configs
|
||||
environment variables
|
||||
#+end_src
|
||||
|
||||
|
||||
Why they mention differences
|
||||
|
||||
Your service is:
|
||||
|
||||
~Web API~
|
||||
|
||||
instead of
|
||||
|
||||
~Background Windows Service~
|
||||
|
||||
So deployment might differ:
|
||||
|
||||
| Background service | Web API |
|
||||
| ------------------ | ----------------------- |
|
||||
| runs as service | hosted in IIS / kestrel |
|
||||
| app.config | appsettings.json |
|
||||
|
||||
Result of Task 2
|
||||
|
||||
You can now run:
|
||||
|
||||
local TMC deployment
|
||||
|
||||
and your API launches locally.
|
||||
|
||||
*** Task 3: Deploy to QA (Toblerone)
|
||||
|
||||
Now you move from:
|
||||
|
||||
Local → QA
|
||||
|
||||
"Toblerone" appears to be a **specific QA environment/server**.
|
||||
|
||||
|
||||
You update manifests like:
|
||||
|
||||
deploy_all.yml
|
||||
|
||||
Which probably contains:
|
||||
|
||||
#+begin_src yaml
|
||||
|
||||
|
||||
apps:
|
||||
- driverwebapi
|
||||
- sitevisitswebapi
|
||||
#+end_src
|
||||
|
||||
So the deployment engine knows:
|
||||
|
||||
deploy this service in QA
|
||||
|
||||
|
||||
Then test deployment.
|
||||
|
||||
|
||||
*** Task 4: Add to Ad-hoc QA / Cert Pipelines
|
||||
|
||||
These are **manual release pipelines**.
|
||||
|
||||
Example use:
|
||||
|
||||
~Dev: deploy specific service to QA quickly~
|
||||
|
||||
|
||||
Instead of full release.
|
||||
|
||||
You add the artifact there so people can manually deploy it.
|
||||
|
||||
|
||||
*** Task 5: Endpoint Testing
|
||||
|
||||
Critical step.
|
||||
|
||||
You must confirm the new API behaves **exactly like the old one**.
|
||||
|
||||
Because they plan a **hotswap**.
|
||||
|
||||
Meaning:
|
||||
|
||||
Old API → replace with new API
|
||||
same URL
|
||||
same behaviour
|
||||
|
||||
If anything changes, clients break
|
||||
|
||||
So test:
|
||||
|
||||
Auth
|
||||
Request formats
|
||||
Response formats
|
||||
Error codes
|
||||
|
||||
|
||||
*** Task 6: Deploy to Remaining QA
|
||||
|
||||
Once Toblerone works:
|
||||
|
||||
Toblerone QA → All QA environments
|
||||
|
||||
Example:
|
||||
|
||||
QA1
|
||||
QA2
|
||||
QA3
|
||||
|
||||
Maybe also:
|
||||
|
||||
Internal CERT
|
||||
|
||||
|
||||
*** Task 7: Logging (Serilog → Elastic)
|
||||
|
||||
The new API logs differently.
|
||||
|
||||
Probably something like:
|
||||
|
||||
~logs/sitevisitswebapi/*.log~
|
||||
|
||||
|
||||
Filebeat must be told to collect them.
|
||||
|
||||
Example config:
|
||||
|
||||
#+begin_src
|
||||
- type: log
|
||||
paths:
|
||||
- /logs/sitevisitswebapi/*.log
|
||||
#+end_src
|
||||
|
||||
Then logs go:
|
||||
|
||||
~Server → Filebeat → Elasticsearch → Kibana~
|
||||
|
||||
|
||||
*** Task 8: Deploy to UAT
|
||||
|
||||
UAT = staging environment.
|
||||
|
||||
Production-like testing
|
||||
|
||||
Here you update the deployment manifests to use the **new API**.
|
||||
|
||||
|
||||
|
||||
*** Task 9: Deploy to Live
|
||||
|
||||
Final production rollout.
|
||||
|
||||
Same process:
|
||||
|
||||
manifest updates
|
||||
deploy pipeline
|
||||
verification
|
||||
|
||||
|
||||
** 4. The Entire Flow (Visual)
|
||||
|
||||
#+begin_src
|
||||
|
||||
|
||||
Code (SiteVisitsWebApi)
|
||||
│
|
||||
▼
|
||||
Build Pipeline
|
||||
│
|
||||
▼
|
||||
Artifact Produced
|
||||
(SiteVisitsWebApi.zip)
|
||||
│
|
||||
▼
|
||||
TMC Release Pipeline
|
||||
│
|
||||
▼
|
||||
Deployment Manifests
|
||||
│
|
||||
▼
|
||||
Local Deploy
|
||||
│
|
||||
▼
|
||||
QA (Toblerone)
|
||||
│
|
||||
▼
|
||||
All QA
|
||||
│
|
||||
▼
|
||||
UAT
|
||||
│
|
||||
▼
|
||||
LIVE
|
||||
#+end_src
|
||||
|
||||
|
||||
** 5. Why Enterprise Pipelines Feel Complicated
|
||||
|
||||
Because deployment is separated into **many independent systems**:
|
||||
|
||||
| Layer | Responsibility |
|
||||
| ------------------ | ----------------------- |
|
||||
| Build pipeline | compile code |
|
||||
| Artifact storage | store packages |
|
||||
| Release pipeline | orchestrate deployments |
|
||||
| Manifests | describe environments |
|
||||
| Deployment scripts | actually install |
|
||||
| Logging | monitor |
|
||||
|
||||
Each lives in **different repos**.
|
||||
|
||||
|
||||
** 6. The Most Important Concept to Understand
|
||||
|
||||
Everything revolves around **artifacts**.
|
||||
|
||||
#+begin_src
|
||||
Source Code
|
||||
↓
|
||||
Build
|
||||
↓
|
||||
Artifact
|
||||
↓
|
||||
Deploy artifact everywhere
|
||||
#+end_src
|
||||
|
||||
You **never deploy source code directly**.
|
||||
|
||||
|
||||
** 7. What You're Really Doing in This Ticket
|
||||
|
||||
You are teaching the deployment system:
|
||||
|
||||
"Hey, there is a new service now"
|
||||
|
||||
Then gradually making every environment aware of it.
|
||||
|
||||
65
Career Concepts/20260305111610-cicd_summary.org
Normal file
65
Career Concepts/20260305111610-cicd_summary.org
Normal file
@@ -0,0 +1,65 @@
|
||||
:PROPERTIES:
|
||||
:ID: 5b714c6c-7eaf-4f3f-b4f6-2166ff3a9963
|
||||
:END:
|
||||
#+title: CI/CD Summary
|
||||
#+category: Career Concepts
|
||||
|
||||
* Summary
|
||||
CI/CD stands for Continuous Integration and Continuous Delivery/Deployment. It’s a development practice that automates building, testing, and delivering software so code changes can be released quickly and reliably.
|
||||
|
||||
** Continuous Integration (CI)
|
||||
|
||||
CI means developers frequently merge their code into a shared repository. Every time code is pushed:
|
||||
|
||||
1. The code is built automatically.
|
||||
2. Automated tests run.
|
||||
3. If something breaks, the team is alerted.
|
||||
|
||||
Goal: catch bugs early and ensure new code works with the rest of the project.
|
||||
|
||||
** Continuous Delivery / Continuous Deployment (CD)
|
||||
CD takes the tested code from CI and prepares it for release.
|
||||
|
||||
- Continuous Delivery: Code is automatically prepared for production, but a human approves the final deployment.
|
||||
|
||||
- Continuous Deployment: Code is automatically deployed to production with no manual approval.
|
||||
|
||||
Goal: make releases faster and safer.
|
||||
|
||||
** Pipelines
|
||||
A pipeline is the automated workflow that runs these steps in sequence. Think of it as a script that defines what happens after a code change.
|
||||
|
||||
Typical pipeline stages:
|
||||
|
||||
1. Source – code pushed to repository
|
||||
2. Build – compile the application
|
||||
3. Test – run automated tests
|
||||
4. Package – create deployable artifact (e.g., Docker image)
|
||||
5. Deploy – release to staging or production
|
||||
|
||||
Example simplified pipeline:
|
||||
|
||||
~Code Push → Build → Test → Package → Deploy~
|
||||
|
||||
Why CI/CD is useful
|
||||
|
||||
- Faster development cycles
|
||||
|
||||
- Fewer integration bugs
|
||||
|
||||
- Automated testing and deployment
|
||||
|
||||
- More reliable releases
|
||||
|
||||
Common CI/CD tools
|
||||
|
||||
- GitHub Actions
|
||||
|
||||
- Jenkins
|
||||
|
||||
- GitLab CI/CD
|
||||
|
||||
- CircleCI
|
||||
|
||||
In short:
|
||||
CI/CD uses pipelines to automatically build, test, and deploy software whenever code changes are made.
|
||||
244
Career Concepts/20260305130457-database_perms_roles_accounts.org
Normal file
244
Career Concepts/20260305130457-database_perms_roles_accounts.org
Normal file
@@ -0,0 +1,244 @@
|
||||
:PROPERTIES:
|
||||
:ID: b4858f6a-b05c-47f2-972e-905e0bb2c352
|
||||
:END:
|
||||
#+title: Database Permissions, Roles, and Accounts
|
||||
#+category: Career Concepts
|
||||
|
||||
* Introduction
|
||||
Database security is a crucial part of database administration. It ensures that only authorised users can access, modify, or manage data. Three core concepts used to control access are:
|
||||
|
||||
1. Accounts (logins/users)
|
||||
2. Roles
|
||||
3. Permissions
|
||||
|
||||
These concepts work together to create structured and secure access control inside a database system.
|
||||
|
||||
* 1. Database Accounts
|
||||
|
||||
A *database account* represents an identity that can connect to the database system. In Microsoft SQL Server this is typically split into two layers:
|
||||
|
||||
- *Login* → Authentication at the server level
|
||||
- *User* → Authorisation inside a specific database
|
||||
|
||||
** Login (Server Level)
|
||||
|
||||
A login allows someone or something to authenticate with the SQL Server instance.
|
||||
|
||||
Example: Creating a login
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
CREATE LOGIN student_user
|
||||
WITH PASSWORD = 'StrongPassword123!';
|
||||
#+END_SRC
|
||||
|
||||
You can also create a login linked to Windows authentication.
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
CREATE LOGIN [DOMAIN\Zaine] FROM WINDOWS;
|
||||
#+END_SRC
|
||||
|
||||
** Database User
|
||||
|
||||
A login must be mapped to a user inside a database before it can access that database.
|
||||
|
||||
Example:
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
USE SchoolDB;
|
||||
|
||||
CREATE USER student_user
|
||||
FOR LOGIN student_user;
|
||||
#+END_SRC
|
||||
|
||||
Now the login can access the *SchoolDB* database as the user *student_user*.
|
||||
|
||||
* 2. Permissions
|
||||
|
||||
Permissions define *what actions a user can perform*. These actions include reading data, inserting rows, modifying tables, or executing procedures.
|
||||
|
||||
Common SQL Server permissions include:
|
||||
|
||||
- SELECT → Read data
|
||||
- INSERT → Add new data
|
||||
- UPDATE → Modify data
|
||||
- DELETE → Remove data
|
||||
- EXECUTE → Run stored procedures
|
||||
- ALTER → Modify database objects
|
||||
- CONTROL → Full control over an object
|
||||
|
||||
** Granting Permissions
|
||||
|
||||
Permissions are given using the *GRANT* statement.
|
||||
|
||||
Example: Allow a user to read data from a table.
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
GRANT SELECT
|
||||
ON Students
|
||||
TO student_user;
|
||||
#+END_SRC
|
||||
|
||||
** Grant Multiple Permissions
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
GRANT SELECT, INSERT
|
||||
ON Students
|
||||
TO student_user;
|
||||
#+END_SRC
|
||||
|
||||
This allows the user to read and add new rows.
|
||||
|
||||
** Revoking Permissions
|
||||
|
||||
If a permission should be removed:
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
REVOKE INSERT
|
||||
ON Students
|
||||
FROM student_user;
|
||||
#+END_SRC
|
||||
|
||||
** Denying Permissions
|
||||
|
||||
A *DENY* explicitly blocks an action, even if another role grants it.
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
DENY DELETE
|
||||
ON Students
|
||||
TO student_user;
|
||||
#+END_SRC
|
||||
|
||||
* 3. Roles
|
||||
|
||||
Roles are collections of permissions that can be assigned to multiple users. They simplify permission management by allowing administrators to assign permissions once and reuse them.
|
||||
|
||||
Instead of granting permissions to many individual users, you grant them to a role.
|
||||
|
||||
Example scenario:
|
||||
|
||||
- Many students should be able to view course data.
|
||||
- Instead of assigning permissions to each student individually, create a role.
|
||||
|
||||
** Creating a Role
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
CREATE ROLE student_role;
|
||||
#+END_SRC
|
||||
|
||||
** Assign Permissions to the Role
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
GRANT SELECT
|
||||
ON Courses
|
||||
TO student_role;
|
||||
#+END_SRC
|
||||
|
||||
** Add Users to the Role
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
ALTER ROLE student_role
|
||||
ADD MEMBER student_user;
|
||||
#+END_SRC
|
||||
|
||||
Now *student_user* inherits all permissions from *student_role*.
|
||||
|
||||
* 4. Built-in Database Roles
|
||||
|
||||
SQL Server includes several predefined roles that already have common permission sets.
|
||||
|
||||
Examples:
|
||||
|
||||
| Role Name | Purpose |
|
||||
|---------------+-----------------------------------|
|
||||
| db_owner | Full control over the database |
|
||||
| db_datareader | Read all tables |
|
||||
| db_datawriter | Insert/update/delete all tables |
|
||||
| db_ddladmin | Create or modify database objects |
|
||||
|
||||
Example: Add a user to the read-only role.
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
ALTER ROLE db_datareader
|
||||
ADD MEMBER student_user;
|
||||
#+END_SRC
|
||||
|
||||
This allows the user to read all tables without giving modification rights.
|
||||
|
||||
* 5. Example: Simple University Database Security
|
||||
|
||||
Assume a database called *UniversityDB* with two tables:
|
||||
|
||||
- Students
|
||||
- Courses
|
||||
|
||||
Goal:
|
||||
|
||||
- Students → Read course information
|
||||
- Teachers → Modify course data
|
||||
- Admin → Full control
|
||||
|
||||
** Step 1: Create Roles
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
CREATE ROLE student_role;
|
||||
CREATE ROLE teacher_role;
|
||||
CREATE ROLE admin_role;
|
||||
#+END_SRC
|
||||
|
||||
** Step 2: Assign Permissions
|
||||
|
||||
Student role (read-only):
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
GRANT SELECT
|
||||
ON Courses
|
||||
TO student_role;
|
||||
#+END_SRC
|
||||
|
||||
Teacher role:
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
GRANT SELECT, INSERT, UPDATE
|
||||
ON Courses
|
||||
TO teacher_role;
|
||||
#+END_SRC
|
||||
|
||||
Admin role:
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
GRANT CONTROL
|
||||
ON DATABASE::UniversityDB
|
||||
TO admin_role;
|
||||
#+END_SRC
|
||||
|
||||
** Step 3: Add Users
|
||||
|
||||
#+BEGIN_SRC sql
|
||||
ALTER ROLE student_role ADD MEMBER student_user;
|
||||
ALTER ROLE teacher_role ADD MEMBER teacher_user;
|
||||
ALTER ROLE admin_role ADD MEMBER admin_user;
|
||||
#+END_SRC
|
||||
|
||||
Now permissions are organised through roles instead of assigning them individually.
|
||||
|
||||
* 6. Why Roles Are Important
|
||||
|
||||
Roles provide several benefits:
|
||||
|
||||
- *Simpler management* → Change permissions in one place
|
||||
- *Scalability* → Works well with many users
|
||||
- *Security consistency* → Reduces risk of incorrect permissions
|
||||
- *Easier auditing* → Clear structure of access control
|
||||
|
||||
Without roles, administrators would need to manually manage permissions for every individual user.
|
||||
|
||||
* Summary
|
||||
|
||||
Database access control relies on three key components:
|
||||
|
||||
- *Accounts* identify who is accessing the system (logins and users).
|
||||
- *Permissions* define what actions can be performed.
|
||||
- *Roles* group permissions together for easier management.
|
||||
|
||||
In Microsoft SQL Server, administrators typically create logins, map them to database users, assign them to roles, and grant permissions to those roles. This layered approach ensures a secure and manageable database system.
|
||||
|
||||
318
Career Concepts/20260305132058-restful_api.org
Normal file
318
Career Concepts/20260305132058-restful_api.org
Normal file
@@ -0,0 +1,318 @@
|
||||
:PROPERTIES:
|
||||
:ID: 6a5bf6dd-d0ec-43e4-8e07-9956f4715f10
|
||||
:END:
|
||||
#+title: RESTful APIs
|
||||
#+category: Career Concepts
|
||||
|
||||
* What is a RESTful API?
|
||||
|
||||
A *RESTful API* is a web service that follows the principles of *REST (Representational State Transfer)*. REST is an architectural style used for designing networked applications.
|
||||
|
||||
In a RESTful system:
|
||||
|
||||
- Everything is treated as a *resource*
|
||||
- Resources are identified using *URLs*
|
||||
- Standard *HTTP methods* are used to interact with resources
|
||||
- Communication is usually done using *JSON*
|
||||
|
||||
Example resource:
|
||||
|
||||
#+begin_src
|
||||
/users
|
||||
/users/1
|
||||
/users/1/orders
|
||||
#+end_src
|
||||
|
||||
These represent data stored on the server.
|
||||
|
||||
* Core HTTP Methods
|
||||
|
||||
REST APIs rely heavily on HTTP verbs.
|
||||
|
||||
| Method | Purpose | Example Endpoint |
|
||||
|--------+-----------------------------+------------------|
|
||||
| GET | Retrieve data | GET /users |
|
||||
| POST | Create a new resource | POST /users |
|
||||
| PUT | Update an existing resource | PUT /users/1 |
|
||||
| DELETE | Remove a resource | DELETE /users/1 |
|
||||
|
||||
* Example Resource: User
|
||||
|
||||
Assume we have a simple *User* resource:
|
||||
|
||||
#+begin_src json
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Alice",
|
||||
"email": "alice@email.com"
|
||||
}
|
||||
#+end_src
|
||||
|
||||
The API allows clients to create, read, update, and delete users.
|
||||
|
||||
* Creating a REST API in C# (ASP.NET Core)
|
||||
|
||||
In C#, REST APIs are commonly built using *ASP.NET Core Web API*.
|
||||
|
||||
Example project creation:
|
||||
|
||||
#+begin_src bash
|
||||
dotnet new webapi -n UserApi
|
||||
cd UserApi
|
||||
dotnet run
|
||||
#+end_src
|
||||
|
||||
This creates a ready-to-run REST API project.
|
||||
|
||||
* Defining a Model
|
||||
|
||||
First, define the resource model.
|
||||
|
||||
File: Models/User.cs
|
||||
|
||||
#+begin_src csharp
|
||||
namespace UserApi.Models
|
||||
{
|
||||
public class User
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Email { get; set; }
|
||||
}
|
||||
}
|
||||
#+end_src
|
||||
|
||||
This represents the data stored and returned by the API.
|
||||
|
||||
* Creating a Controller
|
||||
|
||||
Controllers handle HTTP requests.
|
||||
|
||||
File: Controllers/UserController.cs
|
||||
|
||||
#+begin_src csharp
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using UserApi.Models;
|
||||
|
||||
namespace UserApi.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class UserController : ControllerBase
|
||||
{
|
||||
private static List<User> users = new List<User>()
|
||||
{
|
||||
new User { Id = 1, Name = "Alice", Email = "alice@email.com" },
|
||||
new User { Id = 2, Name = "Bob", Email = "bob@email.com" }
|
||||
};
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult<List<User>> GetUsers()
|
||||
{
|
||||
return Ok(users);
|
||||
}
|
||||
}
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Endpoint created:
|
||||
|
||||
#+begin_src
|
||||
GET /api/user
|
||||
#+end_src
|
||||
|
||||
Response:
|
||||
|
||||
#+begin_src json
|
||||
[
|
||||
{ "id": 1, "name": "Alice", "email": "alice@email.com" },
|
||||
{ "id": 2, "name": "Bob", "email": "bob@email.com" }
|
||||
]
|
||||
#+end_src
|
||||
|
||||
* Getting a Single Resource
|
||||
|
||||
Add an endpoint to retrieve a specific user.
|
||||
|
||||
#+begin_src csharp
|
||||
[HttpGet("{id}")]
|
||||
public ActionResult<User> GetUser(int id)
|
||||
{
|
||||
var user = users.FirstOrDefault(u => u.Id == id);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(user);
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Endpoint:
|
||||
|
||||
#+begin_src
|
||||
GET /api/user/1
|
||||
#+end_src
|
||||
|
||||
* Creating a Resource (POST)
|
||||
|
||||
Clients send JSON data to create a new user.
|
||||
|
||||
#+begin_src csharp
|
||||
[HttpPost]
|
||||
public ActionResult<User> CreateUser(User newUser)
|
||||
{
|
||||
newUser.Id = users.Max(u => u.Id) + 1;
|
||||
users.Add(newUser);
|
||||
|
||||
return CreatedAtAction(nameof(GetUser), new { id = newUser.Id }, newUser);
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Example request:
|
||||
|
||||
#+begin_src json
|
||||
POST /api/user
|
||||
|
||||
{
|
||||
"name": "Charlie",
|
||||
"email": "charlie@email.com"
|
||||
}
|
||||
#+end_src
|
||||
|
||||
* Updating a Resource (PUT)
|
||||
|
||||
#+begin_src csharp
|
||||
[HttpPut("{id}")]
|
||||
public IActionResult UpdateUser(int id, User updatedUser)
|
||||
{
|
||||
var user = users.FirstOrDefault(u => u.Id == id);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
user.Name = updatedUser.Name;
|
||||
user.Email = updatedUser.Email;
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Endpoint:
|
||||
|
||||
#+begin_src
|
||||
PUT /api/user/1
|
||||
#+end_src
|
||||
|
||||
* Deleting a Resource
|
||||
|
||||
#+begin_src csharp
|
||||
[HttpDelete("{id}")]
|
||||
public IActionResult DeleteUser(int id)
|
||||
{
|
||||
var user = users.FirstOrDefault(u => u.Id == id);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
users.Remove(user);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Endpoint:
|
||||
|
||||
#+begin_src
|
||||
DELETE /api/user/1
|
||||
#+end_src
|
||||
|
||||
* REST Principles
|
||||
|
||||
A good REST API should follow these key ideas:
|
||||
|
||||
** 1. Statelessness
|
||||
|
||||
Each request contains all information needed.
|
||||
|
||||
The server does *not store client session state*.
|
||||
|
||||
** 2. Resource-Based URLs
|
||||
|
||||
Endpoints should represent *nouns*, not verbs.
|
||||
|
||||
Good:
|
||||
|
||||
#+begin_src
|
||||
GET /users
|
||||
POST /users
|
||||
GET /users/1
|
||||
#+end_src
|
||||
|
||||
Bad:
|
||||
|
||||
#+begin_src
|
||||
GET /getUsers
|
||||
POST /createUser
|
||||
#+end_src
|
||||
|
||||
** 3. Standard HTTP Status Codes
|
||||
|
||||
| Code | Meaning |
|
||||
|------+--------------|
|
||||
| 200 | OK |
|
||||
| 201 | Created |
|
||||
| 204 | No Content |
|
||||
| 400 | Bad Request |
|
||||
| 404 | Not Found |
|
||||
| 500 | Server Error |
|
||||
|
||||
* Example Full API Structure
|
||||
|
||||
#+begin_src
|
||||
UserApi/
|
||||
├── Controllers/
|
||||
│ └── UserController.cs
|
||||
├── Models/
|
||||
│ └── User.cs
|
||||
├── Program.cs
|
||||
└── appsettings.json
|
||||
#+end_src
|
||||
|
||||
* Testing the API
|
||||
|
||||
You can test APIs using tools like:
|
||||
|
||||
- curl
|
||||
- Postman
|
||||
- Swagger UI (included with ASP.NET)
|
||||
|
||||
Example curl request:
|
||||
|
||||
#+begin_src bash
|
||||
curl http://localhost:5000/api/user
|
||||
#+end_src
|
||||
|
||||
* Summary
|
||||
|
||||
A RESTful API:
|
||||
|
||||
- Exposes *resources via URLs*
|
||||
- Uses *HTTP methods (GET, POST, PUT, DELETE)*
|
||||
- Communicates typically using *JSON*
|
||||
- Is *stateless*
|
||||
- Returns *standard HTTP status codes*
|
||||
|
||||
In C#, *ASP.NET Core Web API* makes building REST APIs straightforward using:
|
||||
|
||||
- Models
|
||||
- Controllers
|
||||
- Routing
|
||||
- Built-in JSON serialization
|
||||
Reference in New Issue
Block a user