Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

CDP-8328: add normandie status and knox status to ping requests and hosts_and_agents sql table #1744

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,5 @@ MANIFEST
docs/docs_generator/bin/

# Bazel
bazel-bin
bazel-out
bazel-testlogs
bazel-weave
bazel-deploy-agent
bazel-*
MODULE.bazel*
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ Check out [Integrate with Teletraan](https://github.com/pinterest/teletraan/wiki

[Quick start guide!](https://github.com/pinterest/teletraan/wiki/Quickstart-Guide)

#### Before you commit new code

1. Install [pre-commit](https://pre-commit.com/#install)
```bash
cd teletraan
pip install pre-commit
pre-commit install
```


### Documentation

[Check out our wiki!](https://github.com/pinterest/teletraan/wiki)
Expand Down
2 changes: 2 additions & 0 deletions deploy-agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ See https://github.com/pinterest/teletraan/wiki for more details.

1. Install [pre-commit](https://pre-commit.com/#install)
```bash
cd teletraan
pip install pre-commit
pre-commit install
```
Expand All @@ -15,6 +16,7 @@ Ensure that your python version is at least python3.8.

## Building
```bash
cd teletraan/deploy-agent/
sudo bazel build //deployd:deploy-agent
```

Expand Down
52 changes: 49 additions & 3 deletions deploy-agent/deployd/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
import socket
import traceback
import json
from pathlib import Path
import re
import subprocess

from deployd.client.base_client import BaseClient
from deployd.client.restfulclient import RestfulClient
Expand All @@ -32,6 +35,9 @@

log = logging.getLogger(__name__)

NORMANDIE_CERT_FILEPATH = "/var/lib/normandie/fuse/cert/generic"
SAN_URI_PATTERN = r"URI:(\S+),?"


class Client(BaseClient):
def __init__(self, config=None, hostname=None, ip=None, hostgroup=None,
Expand All @@ -51,6 +57,8 @@ def __init__(self, config=None, hostname=None, ip=None, hostgroup=None,
# keep trying to fetch it from facter every time
self._stage_type_fetched = False
self._account_id = None
self._normandie_status = None
self._knox_status = None

def _read_host_info(self) -> bool:
if self._use_facter:
Expand Down Expand Up @@ -196,10 +204,20 @@ def _read_host_info(self) -> bool:
info = json.loads(ec2_metadata)
self._account_id = info.get('AccountId', None)

# Retrieve Normandie status
spiffId = self.get_spiffe_id_from_normandie()
if spiffId:
self._normandie_status = 'OK'
else:
self._normandie_status = 'ERROR'

# TODO retrieve knox status
self._knox_status = 'NotImplementedYet'

log.info("Host information is loaded. "
"Host name: {}, IP: {}, host id: {}, agent_version={}, autoscaling_group: {}, "
"availability_zone: {}, ec2_tags: {}, stage_type: {}, group: {}, account id: {}".format(self._hostname, self._ip, self._id,
self._agent_version, self._autoscaling_group, self._availability_zone, self._ec2_tags, self._stage_type, self._hostgroup, self._account_id))
"availability_zone: {}, ec2_tags: {}, stage_type: {}, group: {}, account id: {}, normandie_status: {}, knox_status: {}".format(self._hostname, self._ip, self._id,
self._agent_version, self._autoscaling_group, self._availability_zone, self._ec2_tags, self._stage_type, self._hostgroup, self._account_id, self._normandie_status, self._knox_status))

if not self._availability_zone:
log.error("Fail to read host info: availablity zone")
Expand All @@ -209,6 +227,32 @@ def _read_host_info(self) -> bool:

return True

def get_spiffe_id_from_normandie(self) -> Optional[str]:
path = Path(NORMANDIE_CERT_FILEPATH)
cmd = [
"openssl",
"x509",
"-in",
path.as_posix(),
"-noout",
"-text",
"-certopt",
"no_subject,no_header,no_version,no_serial,no_signame,no_validity,no_issuer,no_pubkey,no_sigdump,no_aux",
]
matcher = None
try:
cert = subprocess.check_output(cmd).decode("utf-8")
except subprocess.CalledProcessError as e:
log.exception(f"failed to get spiffe id from normandie: {e}")
return None
else:
matcher = re.search(SAN_URI_PATTERN, cert)

if matcher:
return matcher.group(1)

return None

def send_reports(self, env_reports=None) -> Optional[PingResponse]:
try:
if self._read_host_info():
Expand All @@ -229,7 +273,9 @@ def send_reports(self, env_reports=None) -> Optional[PingResponse]:
availabilityZone=self._availability_zone,
ec2Tags=self._ec2_tags,
stageType=self._stage_type,
accountId=self._account_id)
accountId=self._account_id,
normandieStatus=self._normandie_status,
knoxStatus=self._knox_status)

with create_stats_timer('deploy.agent.request.latency',
tags={'host': self._hostname}):
Expand Down
21 changes: 14 additions & 7 deletions deploy-agent/deployd/types/ping_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -20,7 +20,8 @@
class PingRequest(object):

def __init__(self, hostId=None, hostName=None, hostIp=None, groups=None, reports=None,
agentVersion=None, autoscalingGroup=None, availabilityZone=None, ec2Tags=None, stageType=None, accountId=None):
agentVersion=None, autoscalingGroup=None, availabilityZone=None, ec2Tags=None, stageType=None,
accountId=None, normandieStatus=None, knoxStatus=None):
self.hostId = hostId
self.hostName = hostName
self.hostIp = hostIp
Expand All @@ -32,6 +33,8 @@ def __init__(self, hostId=None, hostName=None, hostIp=None, groups=None, reports
self.ec2Tags = ec2Tags
self.stageType = stageType
self.accountId = accountId
self.normandieStatus = normandieStatus
self.knoxStatus = knoxStatus

def to_json(self):
ping_requests = {}
Expand All @@ -52,6 +55,10 @@ def to_json(self):
ping_requests["accountId"] = self.accountId
if self.ec2Tags:
ping_requests["ec2Tags"] = self.ec2Tags
if self.normandieStatus:
ping_requests["normandieStatus"] = self.normandieStatus
if self.knoxStatus:
ping_requests["knoxStatus"] = self.knoxStatus

ping_requests["reports"] = []
for report in self.reports:
Expand All @@ -76,16 +83,16 @@ def to_json(self):
ping_report["deployAlias"] = report.deployAlias
ping_report["containerHealthStatus"] = report.containerHealthStatus
ping_report["agentState"] = report.state

if report.extraInfo:
ping_report["extraInfo"] = \
json.dumps(report.extraInfo, ensure_ascii=False).encode('utf8')

ping_requests["reports"].append(ping_report)
return ping_requests

def __str__(self):
return "PingRequest(hostId={}, hostName={}, hostIp={}, agentVersion={}, autoscalingGroup={}, " \
"availabilityZone={}, ec2Tags={}, stageType={}, groups={}, accountId={}, reports={})".format(self.hostId, self.hostName,
"availabilityZone={}, ec2Tags={}, stageType={}, groups={}, accountId={}, normandieStatus={}, knoxStatus={}, reports={})".format(self.hostId, self.hostName,
self.hostIp, self.agentVersion, self.autoscalingGroup, self.availabilityZone, self.ec2Tags, self.stageType,
self.groups, self.accountId, ",".join(str(v) for v in self.reports))
self.groups, self.accountId, self.normandieStatus, self.knoxStatus, ",".join(str(v) for v in self.reports))
9 changes: 9 additions & 0 deletions deploy-agent/tests/unit/deploy/client/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ def test_read_host_info(self):
self.assertIsNotNone(client._ip)
self.assertTrue(return_value)

def test_read_host_info_normandie(self):
client = Client(config=Config())
client._ec2_tags = {}
client._availability_zone = "us-east-1"
return_value: bool = client._read_host_info()
self.assertIsNotNone(client._normandie_status)
self.assertEquals(client._normandie_status, 'OK')
self.assertTrue(return_value)

def test_read_host_info_no_ec2_tags_provided(self):
client = Client(config=Config())
with self.assertRaises(AttributeError):
Expand Down
6 changes: 6 additions & 0 deletions deploy-service/common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -207,5 +207,11 @@
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,17 @@
package com.pinterest.deployservice.bean;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;

import lombok.Data;

@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class HostAgentBean implements Updatable {
@JsonProperty("hostName")
private String host_name;
Expand All @@ -40,61 +49,11 @@ public class HostAgentBean implements Updatable {
@JsonProperty("autoScalingGroup")
private String auto_scaling_group;

public String getHost_name() {
return host_name;
}

public void setHost_name(String host_name) {
this.host_name = host_name;
}

public String getIp() {
return ip;
}

public void setIp(String ip) {
this.ip = ip;
}

public String getHost_id() {
return host_id;
}

public void setHost_id(String host_id) {
this.host_id = host_id;
}

public Long getCreate_date() {
return create_date;
}
@JsonProperty("normandieStatus")
private String normandie_status;

public void setCreate_date(Long create_date) {
this.create_date = create_date;
}

public Long getLast_update() {
return last_update;
}

public void setLast_update(Long last_update) {
this.last_update = last_update;
}

public String getAgent_Version() {
return agent_version;
}

public void setAgent_Version(String agent_version) {
this.agent_version = agent_version;
}

public String getAuto_scaling_group() {
return this.auto_scaling_group;
}

public void setAuto_scaling_group(String asg) {
this.auto_scaling_group = asg;
}
@JsonProperty("knoxStatus")
private String knox_status;

@Override
public SetClause genSetClause() {
Expand All @@ -106,6 +65,8 @@ public SetClause genSetClause() {
clause.addColumn("last_update", last_update);
clause.addColumn("agent_version", agent_version);
clause.addColumn("auto_scaling_group", auto_scaling_group);
clause.addColumn("normandie_status", normandie_status);
clause.addColumn("knox_status", knox_status);
return clause;
}

Expand All @@ -115,7 +76,9 @@ public SetClause genSetClause() {
+ "host_id=VALUES(host_id),"
+ "last_update=VALUES(last_update),"
+ "agent_version=VALUES(agent_version),"
+ "auto_scaling_group=VALUES(auto_scaling_group)";
+ "auto_scaling_group=VALUES(auto_scaling_group),"
+ "normandie_status=VALUES(normandie_status),"
+ "knox_status=VALUES(knox_status)";

@Override
public String toString() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public class PingRequestBean {

private String accountId;

private String normandieStatus;

private String knoxStatus;

private List<PingReportBean> reports;

public String getHostId() {
Expand Down Expand Up @@ -127,6 +131,14 @@ public void setAccountId(String accountId) {
this.accountId = accountId;
}

public String getNormandieStatus() { return normandieStatus; }

public void setNormandieStatus(String normandieStatus) { this.normandieStatus = normandieStatus; }

public String getKnoxStatus() { return knoxStatus; }

public void setKnoxStatus(String knoxStatus) { this.knoxStatus = knoxStatus; }

public void setReports(List<PingReportBean> reports) {
this.reports = reports;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ void updateHosts(
}

void updateHostStatus(
String hostId, String hostName, String hostIp, String agentVersion, String asg)
String hostId, String hostName, String hostIp, String agentVersion, String asg,
String normandieStatus, String knoxStatus)
throws Exception {
HostAgentBean hostAgentBean = hostAgentDAO.getHostById(hostId);
long currentTime = System.currentTimeMillis();
Expand All @@ -223,8 +224,10 @@ void updateHostStatus(
hostAgentBean.setHost_name(hostName);
hostAgentBean.setIp(hostIp);
hostAgentBean.setLast_update(currentTime);
hostAgentBean.setAgent_Version(agentVersion);
hostAgentBean.setAgent_version(agentVersion);
hostAgentBean.setAuto_scaling_group(asg);
hostAgentBean.setNormandie_status(normandieStatus);
hostAgentBean.setKnox_status(knoxStatus);

if (!isExisting) {
// First ping
Expand Down Expand Up @@ -830,7 +833,10 @@ public PingResult ping(PingRequestBean pingRequest, boolean rate_limited) throws
String agentVersion =
pingRequest.getAgentVersion() != null ? pingRequest.getAgentVersion() : "UNKNOWN";

this.updateHostStatus(hostId, hostName, hostIp, agentVersion, asg);
String normandieStatus = pingRequest.getNormandieStatus() != null ? pingRequest.getNormandieStatus() : "UNKNOWN";
String knoxStatus = pingRequest.getKnoxStatus() != null ? pingRequest.getKnoxStatus() : "UNKNOWN";

this.updateHostStatus(hostId, hostName, hostIp, agentVersion, asg, normandieStatus, knoxStatus);

// update the host <-> groups mapping
this.updateHosts(hostName, hostIp, hostId, groups, accountId);
Expand Down
Loading
Loading