Skip to content

Commit

Permalink
Add GitHub Actions workflow for publishing to PyPI
Browse files Browse the repository at this point in the history
  • Loading branch information
nitin-bhadauria committed Oct 10, 2024
1 parent a51637c commit 656bac0
Show file tree
Hide file tree
Showing 15 changed files with 1,671 additions and 1 deletion.
40 changes: 40 additions & 0 deletions .github/workflows/pip_publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Publish Python Package

on:
push:
branches:
- main
tags:
- 'v*.*.*'

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Check out code
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9' # or any other version you want to use

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build twine pytest
- name: Run tests
run: pytest tests/

- name: Build package
run: python -m build

- name: Publish to PyPI
if: startsWith(github.ref, 'refs/tags')
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
twine upload dist/*
20 changes: 20 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Include the LICENSE file
include LICENSE

# Include the README and other documentation files
include README.md
include faq.md

# Include example configurations
# recursive-include example *.yml

# Include all source files in the package
recursive-include src *.py

# Include test files
recursive-include tests *.py

# Exclude unwanted files
global-exclude *.pyc
global-exclude __pycache__
global-exclude .DS_Store
244 changes: 243 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,243 @@
# aws-resource-scheduler
# AWS Resource Scheduler

AWS Resource Scheduler is an open-source Python module that automates the start and stop operations for various AWS resources, including EC2 instances, Auto Scaling Groups (ASG), ECS services, RDS databases, and Aurora clusters.

## Features

- Create a bundle of resources using names or tags that need to be started or stopped for a project or team.
- Combine resources from multiple regions or accounts.
- The application checks for resources to become healthy before moving to the next resource, allowing you to decide the sequence and dependency of resources.
- Doesn't require any changes to Tags or infrastructure, making it compatible with resources managed by IaC tools like CDK or Terraform.
- Start and stop AWS resources like EC2 instances, RDS databases, Aurora clusters.
- Scale up and down Auto Scaling Groups and ECS services.
- Schedule operations based on predefined configurations.
- Send notifications to Google Chat, Slack, or Microsoft Teams.

## Installation

```bash
pip install aws-resource-scheduler
```

### Configuration

Create a configuration like below, based on your need.
You can keep more then workload in the same file an decide which one to use for the action.

```yaml
workspaces:
stage:
aws_region: us-west-2
role_arn: arn:aws:iam::123456789012:role/SchedulerRole
storage:
method: parameter_store # Options: 'parameter_store' or 'dynamodb' to store last min,max,desire value for ecs and asg
dynamodb_table: 'ResourceSchedulerTable' # Required if method is 'dynamodb'
notification:
enable: true
platform: google
webhook_url: https://chat.googleapis.com/v1/spaces/XXX/messages?key=YYY&token=ZZZ
ec2:
name:
- instance1
- instance2
tags:
Environment: development
asg:
name:
- asg1
- asg2
ecs:
my-cluster:
- service2
services:
- service1
tags:
name: service2
rds:
name:
- db-instance1
- db-instance2
aurora:
name:
- aurora-cluster1
tags:
Environment: development
```
Use service like YAML Checker <https://yamlchecker.com> to validate your yml config. Also use the status action to make sure that you are targeting correct resource with tags config.
### Arguments
-f, --filename: The configuration file
-w, --workspace: The workspace to use from the config file
-r, --resource: Comma-separated list of AWS resources (e.g., ec2, rds, asg, ecs, aurora)
-a, --action: The action to perform (start, stop, status)
-n, --no-wait: Do not wait for resources to reach desired state after starting or stopping
-t, --threads: Number of threads to use for parallel operations (default: 10)
### Example Usage
To stop EC2 instances, ASG, and ECS services in the stage workspace:
```bash
aws-resource-scheduler -f config-stage.yml -w stage -r ec2,rds,asg,ecs -a stop
```

To start EC2 instances, ASG, and ECS services:
```bash
aws-resource-scheduler -f config-stage.yml -w stage -r ec2,asg,ecs -a start
```

### IAM Role and Permission

To securely interact with AWS resources, create an IAM role with the necessary permissions. Follow these steps:


```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SSMDescribeParameters",
"Effect": "Allow",
"Action": [
"ssm:DescribeParameters"
],
"Resource": "*"
},
{
"Sid": "SSMGetPutParameters",
"Effect": "Allow",
"Action": [
"ssm:GetParameter",
"ssm:PutParameter"
],
"Resource": "arn:aws:ssm:*:*:parameter/scheduler/*"
},
{
"Sid": "EC2DescribeInstances",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeTags"
],
"Resource": "*"
},
{
"Sid": "EC2StartStopInstances",
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:StopInstances"
],
"Resource": "*"
},
{
"Sid": "RDSDescribeInstances",
"Effect": "Allow",
"Action": [
"rds:DescribeDBInstances",
"rds:ListTagsForResource"
],
"Resource": "*"
},
{
"Sid": "RDSStartStopInstances",
"Effect": "Allow",
"Action": [
"rds:StartDBInstance",
"rds:StopDBInstance"
],
"Resource": "arn:aws:rds:*:*:db:*"
},
{
"Sid": "RDSDescribeClusters",
"Effect": "Allow",
"Action": [
"rds:DescribeDBClusters",
"rds:ListTagsForResource"
],
"Resource": "*"
},
{
"Sid": "RDSStartStopClusters",
"Effect": "Allow",
"Action": [
"rds:StartDBCluster",
"rds:StopDBCluster"
],
"Resource": "arn:aws:rds:*:*:cluster:*"
},
{
"Sid": "AutoScalingDescribe",
"Effect": "Allow",
"Action": [
"autoscaling:DescribeAutoScalingGroups",
"application-autoscaling:DescribeScalableTargets",
"application-autoscaling:RegisterScalableTarget",
"application-autoscaling:DeregisterScalableTarget",
"application-autoscaling:DescribeScalingPolicies",
"application-autoscaling:PutScalingPolicy"
],
"Resource": "*"
},
{
"Sid": "AutoScalingUpdateGroups",
"Effect": "Allow",
"Action": [
"autoscaling:UpdateAutoScalingGroup"
],
"Resource": "arn:aws:autoscaling:*:*:autoScalingGroup:*:autoScalingGroupName/*"
},
{
"Sid": "ECSDescribeServices",
"Effect": "Allow",
"Action": [
"ecs:DescribeServices",
"ecs:ListTagsForResource",
"ecs:ListServices"
],
"Resource": "*"
},
{
"Sid": "ECSUpdateServices",
"Effect": "Allow",
"Action": [
"ecs:UpdateService"
],
"Resource": "arn:aws:ecs:*:*:service/*"
},
{
"Sid": "DynamodbStorage",
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:GetItem",
"dynamodb:UpdateItem"
],
"Resource": "arn:aws:dynamodb:*:*:table/ResourceSchedulerTable"
}
]
}
```

You can use Start and stop actions are allowed only on instances tagged with scheduler=true.
Other Services (RDS, Auto Scaling Groups, ECS): Similar tag-based restrictions are applied.

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EC2StartStopInstances",
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:StopInstances"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"ec2:ResourceTag/scheduler": "true"
}
}
}
]
}
```
32 changes: 32 additions & 0 deletions faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## FAQ for AWS Resource Scheduler
Based on the common issues, available solutions, and user concerns with AWS resource scheduling tools like Lambda-based solutions, AWS Systems Manager Quick Setup, and other methods, here's a detailed FAQ for the AWS Resource Scheduler module:

1. Why not make scheduling part of Infrastructure as Code (IaC) using tools like Terraform or CDK?
Answer: Integrating scheduling directly into IaC tools like Terraform or CDK can make your setup rigid, especially when schedules need frequent changes. AWS Resource Scheduler decouples the scheduling logic from your core infrastructure, allowing you to modify start/stop schedules without needing to redeploy the entire infrastructure. This flexibility is essential for scenarios like changing business hours or project needs, where start/stop schedules need to adapt quickly.

2. How is AWS Resource Scheduler different from using AWS Lambda functions with tags?
Answer: Lambda functions can be configured to start/stop instances based on tags, but this typically requires you to write custom scripts and manage the invocation frequency, such as through CloudWatch Events​(Amazon Web Services, Inc.). AWS Resource Scheduler provides a more user-friendly, centralized configuration using YAML files and can manage multiple AWS services (e.g., EC2, RDS, ECS) across regions and accounts with a unified approach. It abstracts the scripting and maintenance of the Lambda logic.

3. How does AWS Resource Scheduler compare to AWS Systems Manager Quick Setup?
Answer: AWS Systems Manager Quick Setup is an easy way to set up schedules for EC2 instances based on tags​(Amazon AWS Docs). However, it is limited primarily to EC2 and focuses on simple start/stop actions. AWS Resource Scheduler offers broader resource management capabilities, such as handling ASG scaling, ECS service updates, and Aurora clusters. Additionally, it supports complex dependencies between resources, making it suitable for environments where multiple services need coordinated actions.

4. Why not just use a Lambda function for scheduling?
Answer: While Lambda functions are a good option for lightweight, custom automation, they can become complex to manage when you need to coordinate multiple services or manage configurations across different environments. AWS Resource Scheduler handles these complexities by offering a structured way to manage schedules, including configuration files and support for both SSM Parameter Store and DynamoDB for storing state information.

5. Can AWS Resource Scheduler manage resources across multiple AWS accounts?
Answer: Yes, AWS Resource Scheduler can manage resources across multiple accounts by leveraging AWS IAM roles for cross-account access. This allows a centralized scheduler to control resources in various accounts without needing individual scripts or Lambda functions in each account.

6. How does it handle the startup sequence of resources with dependencies?
Answer: AWS Resource Scheduler checks the health and readiness of each resource before proceeding to the next. For example, if an RDS database must be available before starting an application hosted on EC2, the scheduler ensures this sequence is respected. This is more efficient than simple tag-based or Lambda solutions, which may require custom logic for such dependencies.

7. What if I already have scripts for starting/stopping instances, why should I switch?
Answer: Custom scripts can be difficult to maintain as the environment grows. AWS Resource Scheduler offers a more maintainable solution by using a configuration-based approach, allowing you to change settings without modifying code. It also provides logging and error handling out of the box, making troubleshooting simpler.
8. Can AWS Resource Scheduler be used in a serverless setup?

Answer: Yes, AWS Resource Scheduler can run from AWS Lambda when packaged into a zip file, allowing you to execute the scheduling logic without maintaining servers. This setup can reduce costs and simplifies deployment, while still benefiting from the centralized configuration.

9. How does AWS Resource Scheduler handle configuration changes?
Answer: Configuration changes can be made directly to the YAML file or by using a versioned configuration stored in an S3 bucket. This flexibility makes it easy to update schedules without needing code changes or redeployments. For example, changing business hours can be done by editing the ci/cd pipeline, cron job or event.

10. Why use DynamoDB instead of Parameter Store for storing state information?
Answer: Parameter Store is suitable for smaller environments where you don't need to manage a large number of records or perform complex queries. DynamoDB, on the other hand, is ideal for scaling to thousands of resources and offers more control over data access patterns. Using DynamoDB allows for centralized state storage, making it possible to manage the scheduler across multiple AWS accounts without replicating configuration data in each account.
37 changes: 37 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "aws-resource-scheduler"
version = "0.1.0"
description = "An open-source solution to start/stop AWS EC2, Autoscaling Group, RDS, Aurora, ECS, and Fargate."
readme = "README.md"
requires-python = ">=3.8"
license = { text = "MIT" }
authors = [
{ name="Nitin Bhadauria", email="[email protected]" },
]
maintainers = [
{ name="Nitin Bhadauria", email="[email protected]" },
]
keywords = ["aws", "scheduler", "automation", "ec2", "rds", "asg", "aurora"]
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
]
dependencies = [
"boto3>=1.20.0",
"PyYAML>=5.4",
"requests>=2.28.2",
]

[project.urls]
Homepage = "https://github.com/cloudstaff-apps/aws-resource-scheduler"
Repository = "https://github.com/cloudstaff-apps/aws-resource-scheduler"
Documentation = "https://github.com/cloudstaff-apps/aws-resource-scheduler#readme"
BugTracker = "https://github.com/cloudstaff-apps/aws-resource-scheduler/issues"

[project.scripts]
aws-resource-scheduler = "aws_resource_scheduler.scheduler:main"
3 changes: 3 additions & 0 deletions src/aws_resource_scheduler/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from aws_resource_scheduler.scheduler import main

__all__ = ['main']
Loading

0 comments on commit 656bac0

Please sign in to comment.