Skip to content

Commit c49cc13

Browse files
committed
HMS-5913: add package dates from RHEL lifecycle
Adds package streams info to package_sources. Pulls package stream info from the roadmap API and adds it to package sources if the RPM name matches. Also adds RHEL EoL as the end date for any package source that is not in the roadmap API. Uses the end date for the latest released version of the matching RHEL major version.
1 parent b502037 commit c49cc13

File tree

9 files changed

+482
-33
lines changed

9 files changed

+482
-33
lines changed

pkg/cache/cache.go

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ type Cache interface {
2828

2929
GetRoadmapAppstreams(ctx context.Context) ([]byte, error)
3030
SetRoadmapAppstreams(ctx context.Context, roadmapAppstreamsResponse []byte)
31+
32+
GetRoadmapRhelLifecycle(ctx context.Context) ([]byte, error)
33+
SetRoadmapRhelLifecycle(ctx context.Context, rhelLifecyleResponse []byte)
3134
}
3235

3336
func Initialize() Cache {

pkg/cache/cache_mock.go

+35
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/cache/noop.go

+9
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,12 @@ func (c *noOpCache) GetRoadmapAppstreams(ctx context.Context) ([]byte, error) {
6464
// SetRoadmapAppstreams a NoOp version to store cached roadmap appstreams check
6565
func (c *noOpCache) SetRoadmapAppstreams(ctx context.Context, response []byte) {
6666
}
67+
68+
// GetRoadmapAppstreams a NoOp version to fetch a cached roadmap rhel lifecycle check
69+
func (c *noOpCache) GetRoadmapRhelLifecycle(ctx context.Context) ([]byte, error) {
70+
return nil, NotFound
71+
}
72+
73+
// SetRoadmapAppstreams a NoOp version to store cached roadmap rhel lifecycle check
74+
func (c *noOpCache) SetRoadmapRhelLifecycle(ctx context.Context, response []byte) {
75+
}

pkg/cache/redis.go

+19
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ func roadmapAppstreamsKey(ctx context.Context) string {
6161
return fmt.Sprintf("roadmap-appstreams:%v", identity.Identity.OrgID)
6262
}
6363

64+
func roadmapRhelLifecycleKey(ctx context.Context) string {
65+
identity := identity.GetIdentity(ctx)
66+
return fmt.Sprintf("roadmap-rhel-lifecycle:%v", identity.Identity.OrgID)
67+
}
68+
6469
// GetAccessList uses the request context to read user information, and then tries to retrieve the role AccessList from the cache
6570
func (c *redisCache) GetAccessList(ctx context.Context) (rbac.AccessList, error) {
6671
accessList := rbac.AccessList{}
@@ -187,6 +192,20 @@ func (c *redisCache) SetRoadmapAppstreams(ctx context.Context, response []byte)
187192
c.client.Set(ctx, key, string(response), config.Get().Clients.Redis.Expiration.SubscriptionCheck)
188193
}
189194

195+
func (c *redisCache) GetRoadmapRhelLifecycle(ctx context.Context) ([]byte, error) {
196+
key := roadmapRhelLifecycleKey(ctx)
197+
buf, err := c.get(ctx, key)
198+
if err != nil {
199+
return nil, fmt.Errorf("redis get error: %w", err)
200+
}
201+
return buf, nil
202+
}
203+
204+
func (c *redisCache) SetRoadmapRhelLifecycle(ctx context.Context, response []byte) {
205+
key := roadmapRhelLifecycleKey(ctx)
206+
c.client.Set(ctx, key, string(response), config.Get().Clients.Redis.Expiration.SubscriptionCheck)
207+
}
208+
190209
func (c *redisCache) get(ctx context.Context, key string) ([]byte, error) {
191210
cmd := c.client.Get(ctx, key)
192211
if errors.Is(cmd.Err(), redis.Nil) {

pkg/clients/roadmap_client/client.go

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313

1414
type RoadmapClient interface {
1515
GetAppstreams(ctx context.Context) (AppstreamsResponse, int, error)
16+
GetRhelLifecycle(ctx context.Context) (LifecycleResponse, int, error)
17+
GetRhelLifecycleForLatestMajorVersions(ctx context.Context) (map[int]LifecycleEntity, error)
1618
}
1719

1820
type roadmapClient struct {

pkg/clients/roadmap_client/roadmap.go

+99
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"io"
1010
"net/http"
11+
"time"
1112

1213
"github.com/content-services/content-sources-backend/pkg/api"
1314
"github.com/content-services/content-sources-backend/pkg/cache"
@@ -35,6 +36,18 @@ type AppstreamEntity struct {
3536
Impl string `json:"impl"`
3637
}
3738

39+
type LifecycleResponse struct {
40+
Data []LifecycleEntity `json:"data"`
41+
}
42+
43+
type LifecycleEntity struct {
44+
Name string `json:"name"`
45+
StartDate string `json:"start_date"`
46+
EndDate string `json:"end_date"`
47+
Major int `json:"major"`
48+
Minor int `json:"minor"`
49+
}
50+
3851
func encodedIdentity(ctx context.Context) (string, error) {
3952
id := identity.GetIdentity(ctx)
4053
jsonIdentity, err := json.Marshal(id)
@@ -107,3 +120,89 @@ func (rc roadmapClient) GetAppstreams(ctx context.Context) (AppstreamsResponse,
107120

108121
return appStreamResp, statusCode, nil
109122
}
123+
124+
func (rc roadmapClient) GetRhelLifecycle(ctx context.Context) (LifecycleResponse, int, error) {
125+
statusCode := http.StatusInternalServerError
126+
server := config.Get().Clients.Roadmap.Server
127+
var err error
128+
var lifecycleResponse LifecycleResponse
129+
var body []byte
130+
131+
appstreams, err := rc.cache.GetRoadmapRhelLifecycle(ctx)
132+
if err != nil && !errors.Is(err, cache.NotFound) {
133+
log.Error().Err(err).Msg("GetAppstreams - error reading from cache")
134+
}
135+
if appstreams != nil {
136+
err = json.Unmarshal(appstreams, &lifecycleResponse)
137+
if err != nil {
138+
return LifecycleResponse{}, statusCode, fmt.Errorf("error during unmarshal response body: %w", err)
139+
}
140+
return lifecycleResponse, http.StatusOK, nil
141+
}
142+
143+
fullPath := server + "/lifecycle/rhel"
144+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fullPath, nil)
145+
if err != nil {
146+
return LifecycleResponse{}, statusCode, fmt.Errorf("error building request: %w", err)
147+
}
148+
149+
if config.Get().Clients.Roadmap.Username != "" && config.Get().Clients.Roadmap.Password != "" {
150+
req.SetBasicAuth(config.Get().Clients.Roadmap.Username, config.Get().Clients.Roadmap.Password)
151+
}
152+
153+
encodedXRHID, err := encodedIdentity(ctx)
154+
if err != nil {
155+
return LifecycleResponse{}, statusCode, fmt.Errorf("error getting encoded XRHID: %w", err)
156+
}
157+
req.Header.Set(api.IdentityHeader, encodedXRHID)
158+
159+
resp, err := rc.client.Do(req)
160+
if resp != nil {
161+
defer resp.Body.Close()
162+
163+
body, err = io.ReadAll(resp.Body)
164+
if err != nil {
165+
return LifecycleResponse{}, statusCode, fmt.Errorf("error reading response body: %w", err)
166+
}
167+
if resp.StatusCode != 0 {
168+
statusCode = resp.StatusCode
169+
}
170+
}
171+
if err != nil {
172+
return LifecycleResponse{}, statusCode, fmt.Errorf("error sending request: %w", err)
173+
}
174+
if statusCode < 200 || statusCode >= 300 {
175+
return LifecycleResponse{}, statusCode, fmt.Errorf("unexpected status code with body: %s", string(body))
176+
}
177+
178+
rc.cache.SetRoadmapRhelLifecycle(ctx, body)
179+
180+
err = json.Unmarshal(body, &lifecycleResponse)
181+
if err != nil {
182+
return LifecycleResponse{}, statusCode, fmt.Errorf("error during unmarshal response body: %w", err)
183+
}
184+
185+
return lifecycleResponse, statusCode, nil
186+
}
187+
188+
func (rc roadmapClient) GetRhelLifecycleForLatestMajorVersions(ctx context.Context) (map[int]LifecycleEntity, error) {
189+
lifecycleResp, _, err := rc.GetRhelLifecycle(ctx)
190+
if err != nil {
191+
return nil, err
192+
}
193+
194+
currentDate := time.Now().UTC().Truncate(24 * time.Hour)
195+
rhelEolMap := make(map[int]LifecycleEntity)
196+
for _, item := range lifecycleResp.Data {
197+
startDate, err := time.Parse("2006-01-02", item.StartDate)
198+
if err != nil {
199+
return nil, err
200+
}
201+
if startDate.Before(currentDate) || startDate.Equal(currentDate) {
202+
if existing, found := rhelEolMap[item.Major]; !found || (item.Minor > existing.Minor) {
203+
rhelEolMap[item.Major] = item
204+
}
205+
}
206+
}
207+
return rhelEolMap, nil
208+
}

pkg/clients/roadmap_client/roadmap_client_mock.go

+65
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)