Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cd906e5

Browse files
hujessicaJessica HuAce Nassribusunkim96
authored
Add cap billing walkthrough tutorial (GoogleCloudPlatform#4494)
Co-authored-by: Jessica Hu <[email protected]> Co-authored-by: Ace Nassri <[email protected]> Co-authored-by: Bu Sun Kim <[email protected]>
1 parent 3720b9e commit cd906e5

File tree

4 files changed

+229
-0
lines changed

4 files changed

+229
-0
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
/appengine/**/*.py @engelke @GoogleCloudPlatform/python-samples-owners
1313
/auth/**/*.py @busunkim96 @GoogleCloudPlatform/python-samples-owners
1414
/automl/**/*.py @telpirion @sirtorry @GoogleCloudPlatform/python-samples-owners
15+
/billing/**/*.py @GoogleCloudPlatform/billing-samples-maintainers @GoogleCloudPlatform/python-samples-owners
1516
/bigquery/**/*.py @shollyman @GoogleCloudPlatform/python-samples-owners
1617
/bigquery_storage/**/*.py @shollyman @GoogleCloudPlatform/python-samples-owners
1718
/bigtable/**/*.py @GoogleCloudPlatform/bigtable-dpe @GoogleCloudPlatform/python-samples-owners

billing/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Cap Billing Example
2+
3+
If you are cost conscious and need to control your environment relative to your budget, then you can use programmatic budget notifications to automate your cost control response based on the budget notification.
4+
5+
For an overview of automated cost control responses, see https://cloud.google.com/billing/docs/how-to/notify.
6+
7+
## Run the walkthrough tutorial
8+
9+
[![Open in Cloud Shell](http://gstatic.com/cloudssh/images/open-btn.svg)](https://console.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2Fpython-docs-samples%2Fbilling&cloudshell_tutorial=walkthroughtutorial.md)

billing/cap-billing-walkthrough.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# Automating cost controls by capping billing
2+
3+
## Overview
4+
5+
In this tutorial, you will learn to automate cost controls by setting up programmatic budget notifications.
6+
Programmatic budget notifications can be used to disable billing, which will stop the usage of paid services for your project.
7+
8+
You may choose to disable billing if you have a hard limit on how much money you can spend on Google Cloud.
9+
This may be the case for students, researchers, or developers working in sandbox environments.
10+
11+
As you complete this guide, you will learn the following skills:
12+
+ Creating a budget
13+
+ Setting up a Pub/Sub topic
14+
+ Connecting a billing account to a Pub/Sub topic
15+
+ Deploying a function
16+
17+
**Time to complete:** About 10 minutes
18+
19+
## Getting started
20+
21+
### Before you begin
22+
23+
Before you attempt this tutorial, you will need:
24+
+ An [active Cloud billing account](https://cloud.google.com/billing/docs/how-to/manage-billing-account#create_a_new_billing_account), where you are a billing admin, or you have been granted the correct level of permissions to complete the steps in this tutorial.
25+
26+
## Understand best practices
27+
28+
We recommend that you configure a separate, single Google Cloud project to contain all of your billing administration needs, including your Cloud Billing-related Pub/Sub topics. Your billing administration Google Cloud project can also be used for things like Cloud Billing Budget API access, Cloud Billing Account API access, Cloud Billing exported data, and so on.
29+
30+
## Select a test project
31+
32+
For this tutorial, select or create a test project. The function will be acting on this project, not the billing administration project.
33+
34+
**Caution:** Using the cap billing example will remove Cloud Billing from your project, shutting down all resources. This may result in resources being irretrievably deleted, with no option to recover services. You can re-enable Cloud Billing, but there is no guarantee of service recovery and manual configuration is required.
35+
36+
<walkthrough-project-setup></walkthrough-project-setup>
37+
38+
```sh
39+
export GOOGLE_CLOUD_PROJECT={{project_id}}
40+
```
41+
42+
## Select a billing administration project
43+
44+
For this tutorial, create a new billing administration project.
45+
46+
<walkthrough-project-setup></walkthrough-project-setup>
47+
48+
## Setup
49+
50+
Set up a default project ID so that you do not need to provide them in commands where those values are required.
51+
52+
```sh
53+
gcloud config set project {{project-id}}
54+
```
55+
56+
Enable the Billing Budgets, Cloud Functions, Cloud Billing, and Cloud Build APIs, which you will need for this tutorial.
57+
```sh
58+
gcloud services enable billingbudgets.googleapis.com cloudfunctions.googleapis.com cloudbilling.googleapis.com cloudbuild.googleapis.com
59+
```
60+
61+
Set up environment variables for your budget, Pub/Sub topic, and function.
62+
```sh
63+
export BUDGET_NAME=billing_cap_budget
64+
export TOPIC_NAME=budget-notification
65+
export FUNCTION_NAME=stop_billing
66+
```
67+
68+
**Next: Learn how to set up programmatic budget notifications**
69+
70+
## Set up programmatic notifications
71+
72+
To set up **programmatic budget notifications**, you must create a Pub/Sub topic, create a Cloud Billing budget, and connect the Cloud Billing budget to the Pub/Sub topic.
73+
74+
### Create a Pub/Sub topic
75+
76+
Create a Pub/Sub topic so that Cloud Billing can publish budget alerts to the topic.
77+
```sh
78+
gcloud pubsub topics create ${TOPIC_NAME}
79+
```
80+
81+
### Connect a billing account
82+
83+
Find your project’s billing account ID with the following command. Copy the billing account ID.
84+
85+
**Note:** If you don’t see a billing account ID, make sure your project is attached to a billing account.
86+
```sh
87+
gcloud beta billing projects describe {{project-id}} | grep billingAccountName
88+
```
89+
90+
Replace <BILLING_ID> with your project’s billing account ID.
91+
```sh
92+
export BILLING_ACCOUNT=<BILLING_ID>
93+
```
94+
**Next: Learn how to create a budget**
95+
96+
## Create a budget
97+
98+
Create a test budget of $100 that is associated with your project’s billing account. This command also specifies the Pub/Sub topic where budget related messages will be sent.
99+
```sh
100+
gcloud alpha billing budgets create \
101+
--billing-account=${BILLING_ACCOUNT} \
102+
--display-name=${BUDGET_NAME} \
103+
--budget-amount=100 \
104+
--all-updates-rule-pubsub-topic="projects/${GOOGLE_CLOUD_PROJECT}/topics/${TOPIC_NAME}"
105+
```
106+
107+
**Next: Learn more about the cap billing function and how to deploy it**
108+
109+
## Deploy the function
110+
111+
This function will remove the billing account associated with the project if the cost amount is higher than the budget amount.
112+
```sh
113+
gcloud functions deploy ${FUNCTION_NAME} \
114+
--runtime=python37 \
115+
--source=./sample_code \
116+
--trigger-topic=${TOPIC_NAME}
117+
```
118+
119+
**Next: Learn about service account permissions and how to configure them**
120+
121+
## Configure service account permissions
122+
123+
During the creation, updating, or deletion of a function, the Cloud Functions service uses the Google Cloud Functions service agent service account. You must grant the service account the proper permissions so that it can disable billing, such as the Billing Admin role.
124+
```sh
125+
gcloud projects add-iam-policy-binding \
126+
${GOOGLE_CLOUD_PROJECT} \
127+
--member='serviceAccount:'${GOOGLE_CLOUD_PROJECT}'@appspot.gserviceaccount.com' \
128+
--role='roles/owner'
129+
```
130+
**Next: Verify that Cloud Billing is disabled**
131+
132+
## Verify that Cloud Billing is disabled
133+
134+
To disable Cloud Billing on your project, publish a sample message in Pub/Sub with the test message below. If successful, the project will no longer be visible under the billing account and resources in the project will be disabled.
135+
```sh
136+
gcloud pubsub topics publish ${TOPIC_NAME} --message='{"costAmount": 100.01,"budgetAmount": 100.00}'
137+
```
138+
139+
Check that your billing account has been removed with this command. If the output is blank, then you have successfully disabled Cloud Billing.
140+
```sh
141+
gcloud beta billing projects describe {{project-id}} | grep billingAccountName
142+
```
143+
144+
**Next: Wrapping up**
145+
146+
## Congratulations!
147+
148+
<walkthrough-conclusion-trophy></walkthrough-conclusion-trophy>
149+
150+
You’ve completed the Cap Billing walkthrough!
151+
152+
**What's Next**
153+
154+
Here are some areas to explore to learn more about automating cost controls:
155+
+ [Sending notifications to Slack](https://cloud.google.com/billing/docs/how-to/notify#send_notifications_to_slack)
156+
+ [Selectively controlling usage of resources](https://cloud.google.com/billing/docs/how-to/notify#selectively_control_usage)

billing/main.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import base64
2+
import json
3+
import os
4+
from googleapiclient import discovery
5+
PROJECT_ID = os.getenv('GCP_PROJECT')
6+
PROJECT_NAME = f'projects/{PROJECT_ID}'
7+
def stop_billing(data, context):
8+
pubsub_data = base64.b64decode(data['data']).decode('utf-8')
9+
pubsub_json = json.loads(pubsub_data)
10+
cost_amount = pubsub_json['costAmount']
11+
budget_amount = pubsub_json['budgetAmount']
12+
if cost_amount <= budget_amount:
13+
print(f'No action necessary. (Current cost: {cost_amount})')
14+
return
15+
16+
if PROJECT_ID is None:
17+
print('No project specified with environment variable')
18+
return
19+
20+
billing = discovery.build(
21+
'cloudbilling',
22+
'v1',
23+
cache_discovery=False,
24+
)
25+
26+
projects = billing.projects()
27+
28+
billing_enabled = __is_billing_enabled(PROJECT_NAME, projects)
29+
30+
if billing_enabled:
31+
__disable_billing_for_project(PROJECT_NAME, projects)
32+
else:
33+
print('Billing already disabled')
34+
35+
36+
def __is_billing_enabled(project_name, projects):
37+
"""
38+
Determine whether billing is enabled for a project
39+
@param {string} project_name Name of project to check if billing is enabled
40+
@return {bool} Whether project has billing enabled or not
41+
"""
42+
try:
43+
res = projects.getBillingInfo(name=project_name).execute()
44+
return res['billingEnabled']
45+
except KeyError:
46+
# If billingEnabled isn't part of the return, billing is not enabled
47+
return False
48+
except Exception:
49+
print('Unable to determine if billing is enabled on specified project, assuming billing is enabled')
50+
return True
51+
52+
53+
def __disable_billing_for_project(project_name, projects):
54+
"""
55+
Disable billing for a project by removing its billing account
56+
@param {string} project_name Name of project disable billing on
57+
"""
58+
body = {'billingAccountName': ''} # Disable billing
59+
try:
60+
res = projects.updateBillingInfo(name=project_name, body=body).execute()
61+
print(f'Billing disabled: {json.dumps(res)}')
62+
except Exception:
63+
print('Failed to disable billing, possibly check permissions')

0 commit comments

Comments
 (0)