Skip to content

Commit

Permalink
Merge pull request #45 from wp-media/develop
Browse files Browse the repository at this point in the history
Release Slack command /wprocket-ips
  • Loading branch information
MathieuLamiot authored Oct 23, 2023
2 parents 3b0cd3c + 9509d40 commit 98f21cd
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .github/workflows/ci-on_pr_main_bash.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ env:
TBTT_SLACK_SIGNING_SECRET: tbtt_slack_signing_secret
TBTT_SLACK_USER_TOKEN: tbtt_slack_user_token
TBTT_GITHUB_WEBHOOK_SECRET: tbtt_github_webhook_secret
TBTT_OVH_APP_KEY: a
TBTT_OVH_APP_SECRET: b
TBTT_OVH_CONSUMER_KEY: c

jobs:
lint-and-test:
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ lazy-object-proxy==1.9.0
MarkupSafe==2.1.3
mccabe==0.7.0
multidict==6.0.4
ovh==1.1.0
packaging==23.1
platformdirs==3.9.1
pluggy==1.2.0
Expand Down
3 changes: 3 additions & 0 deletions sources/TechTeamBot.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ def __setup_keys(self):
self.__load_key("TBTT_SLACK_USER_TOKEN", cst.APP_CONFIG_TOKEN_SLACK_USER_TOKEN)
self.__load_key("TBTT_GITHUB_ACCESS_TOKEN", cst.APP_CONFIG_TOKEN_GITHUB_ACCESS_TOKEN)
self.__load_key("TBTT_GITHUB_WEBHOOK_SECRET", cst.APP_CONFIG_TOKEN_GITHUB_WEBHOOK_SECRET)
self.__load_key("TBTT_OVH_APP_KEY", cst.APP_CONFIG_TOKEN_OVH_APP_KEY)
self.__load_key("TBTT_OVH_APP_SECRET", cst.APP_CONFIG_TOKEN_OVH_APP_SECRET)
self.__load_key("TBTT_OVH_CONSUMER_KEY", cst.APP_CONFIG_TOKEN_OVH_CONSUMER_KEY)

def __setup_slack_interaction_endpoint(self):
"""
Expand Down
64 changes: 64 additions & 0 deletions sources/factories/OvhApiFactory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""
This module defines the factory for OVH API
"""
from flask import current_app
import sources.utils.IpAddress as IpAddress
import sources.utils.Constants as cst
import ovh


class OvhApiFactory():
"""
Class managing the API for OVH
"""
def __init__(self):
"""
The factory instanciates the objects it needed to complete the processing of the request.
"""
self.client = None

def _get_ovh_client(self, app_context):
"""
Return the ovh client and creates it if needed
"""
if self.client is None:
app_context.push()
self.client = ovh.Client(
endpoint='ovh-eu', # Endpoint of API OVH Europe (List of available endpoints)
application_key=current_app.config[cst.APP_CONFIG_TOKEN_OVH_APP_KEY],
application_secret=current_app.config[cst.APP_CONFIG_TOKEN_OVH_APP_SECRET],
consumer_key=current_app.config[cst.APP_CONFIG_TOKEN_OVH_CONSUMER_KEY],
)
return self.client

def get_dedicated_servers(self, app_context):
"""
Retrieves the list of dedicated servers available
"""
client = self._get_ovh_client(app_context)
result = client.get('/dedicated/server', iamTags=None)
return result

def get_dedicated_server_display_name(self, app_context, server_name):
"""
Returns display_name of the dedicated server.
"""
client = self._get_ovh_client(app_context)
service_info = client.get(f'/dedicated/server/{server_name}/serviceInfos')
service_id = service_info["serviceId"]
service = client.get(f'/service/{service_id}')
display_name = service["resource"]["displayName"]
return display_name

def get_dedicated_server_ips(self, app_context, server_name):
"""
Return the IPv6 and IPv4 of a dedicated server
"""
client = self._get_ovh_client(app_context)
raw_result = client.get(f'/dedicated/server/{server_name}/ips')
result = dict()
for ip in raw_result:
ip_split = ip.split("/")
result[IpAddress.validIPAddress(ip_split[0])] = ip
return result
61 changes: 61 additions & 0 deletions sources/handlers/ServerListHandler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""
This module defines the handler for logic related to listing server IPs.
"""
from sources.factories.SlackMessageFactory import SlackMessageFactory
from sources.factories.OvhApiFactory import OvhApiFactory
import sources.utils.IpAddress as IpAddress


class ServerListHandler():
"""
Class managing the business logic related to listing servers WP Media uses.
"""
def __init__(self):
"""
The handler instanciates the objects it needed to complete the processing of the request.
"""
self.slack_message_factory = SlackMessageFactory()
self.ovh_api_factory = OvhApiFactory()

def send_wp_rocket_ips(self, app_context, slack_user):
"""
List all IPs used for WP Rocket and sends it in a Slack DM
"""
text = "List of IPs used for WP Rocket:\n\n"

text += "License validation/activation, update check, plugin information:\n"
# Defined in https://gitlab.one.com/systems/group.one-authdns/-/blob/main/octodns/wp-rocket.me.yaml?ref_type=heads
text += "https://wp-rocket.me / 185.10.9.101\n"
text += "\n"

text += "Load CSS Asynchronously:\n"
# Defined in https://gitlab.one.com/systems/group.one-authdns/-/blob/main/octodns/wp-rocket.me.yaml?ref_type=heads
text += "https://cpcss.wp-rocket.me / 46.30.212.116\n"
# Defined in k8s_sips: https://gitlab.one.com/systems/chef-repo/-/blob/master/roles/onecom-global-firewall-macros.json#L173
text += "46.30.212.64\n46.30.212.65\n46.30.212.66\n46.30.212.67\n46.30.212.68\n46.30.212.69\n46.30.211.85\n"
text += "\n"

text += "Remove Unused CSS:\n"
# Defined in k8s_sips: https://gitlab.one.com/systems/chef-repo/-/blob/master/roles/onecom-global-firewall-macros.json#L173
text += "46.30.212.64\n46.30.212.65\n46.30.212.66\n46.30.212.67\n46.30.212.68\n46.30.212.69\n46.30.211.85\n"
# OVH servers
all_server_list = self.ovh_api_factory.get_dedicated_servers(app_context)
for server_name in all_server_list:
display_name = self.ovh_api_factory.get_dedicated_server_display_name(app_context, server_name)
if 'worker' in display_name:
server_ips = self.ovh_api_factory.get_dedicated_server_ips(app_context, server_name)
text += server_ips[IpAddress.IP_ADDRESS_IPV4] + " / " + server_ips[IpAddress.IP_ADDRESS_IPV6] + "\n"
text += "\n"

text += "Dynamic exclusions and inclusions:\n"
# Defined in https://gitlab.one.com/systems/group.one-authdns/-/blob/main/octodns/wp-rocket.me.yaml?ref_type=heads
text += "https://b.rucss.wp-rocket.me / 46.30.212.116\n"
text += "\n"

text += "RocketCDN subscription:\n"
text += "https://rocketcdn.me/api/\n"
# Defined in k8s_sips: https://gitlab.one.com/systems/chef-repo/-/blob/master/roles/onecom-global-firewall-macros.json#L173
text += "46.30.212.64\n46.30.212.65\n46.30.212.66\n46.30.212.67\n46.30.212.68\n46.30.212.69\n46.30.211.85\n"

self.slack_message_factory.post_message(app_context, slack_user, text)
16 changes: 15 additions & 1 deletion sources/handlers/SlackCommandHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from threading import Thread
from flask import current_app
from sources.factories.SlackModalFactory import SlackModalFactory
from sources.handlers.ServerListHandler import ServerListHandler


class SlackCommandHandler():
Expand All @@ -18,6 +19,7 @@ def __init__(self):
The handler instanciates the objects it needed to complete the processing of the request.
"""
self.slack_modal_factory = SlackModalFactory()
self.server_list_handler = ServerListHandler()

def process(self, payload_json):
"""
Expand All @@ -27,10 +29,11 @@ def process(self, payload_json):

# Retrieve the shortcut callback
command = payload_json['command']

# Process the paylaod according to the callback
if '/dev-team-escalation' == command:
self.dev_team_escalation_command_callback(payload_json)
elif '/wprocket-ips' == command:
self.wp_rocket_ips_command_callback(payload_json)
else:
raise ValueError('Unknown command.')
return {}
Expand All @@ -46,3 +49,14 @@ def dev_team_escalation_command_callback(self, payload_json):
target=self.slack_modal_factory.dev_team_escalation_modal, kwargs={
"app_context": current_app.app_context(), "trigger_id": trigger_id})
thread.start()

def wp_rocket_ips_command_callback(self, payload_json):
"""
Callback method to process the Slack command "/wprocket-ips"
"""
initiator = payload_json["user_id"]

thread = Thread(
target=self.server_list_handler.send_wp_rocket_ips, kwargs={
"app_context": current_app.app_context(), "slack_user": initiator})
thread.start()
3 changes: 3 additions & 0 deletions sources/utils/Constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
APP_CONFIG_TOKEN_SLACK_USER_TOKEN = 'SLACK_USER_TOKEN'
APP_CONFIG_TOKEN_GITHUB_ACCESS_TOKEN = 'GITHUB_ACCESS_TOKEN'
APP_CONFIG_TOKEN_GITHUB_WEBHOOK_SECRET = 'GITHUB_WEBHOOK_SECRET'
APP_CONFIG_TOKEN_OVH_APP_KEY = 'OVH_APP_KEY'
APP_CONFIG_TOKEN_OVH_APP_SECRET = 'OVH_APP_SECRET'
APP_CONFIG_TOKEN_OVH_CONSUMER_KEY = 'OVH_CONSUMER_KEY'
17 changes: 17 additions & 0 deletions sources/utils/IpAddress.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""
Utility functions to handle IP Addresses.
"""
from ipaddress import ip_address, IPv4Address

IP_ADDRESS_IPV4 = "IPv4"
IP_ADDRESS_IPV6 = "IPv6"


def validIPAddress(IP: str) -> str:
"""
Checks the IP address provided to identify if it is IPv4 or IPv6 or invalid.
"""
try:
return IP_ADDRESS_IPV4 if type(ip_address(IP)) is IPv4Address else IP_ADDRESS_IPV6
except ValueError:
return "Invalid"

0 comments on commit 98f21cd

Please sign in to comment.