-
Notifications
You must be signed in to change notification settings - Fork 29
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
Platforms connection in health-check #325
Changes from 31 commits
4139ea3
144ea91
61157b4
9f62a81
81ff665
115e2a4
37f9bc4
4f21ed9
421d88f
30ab52e
d25a87d
794c3b0
40fb02b
37c03dd
f138807
ce4d4bb
3a34381
91eb2a9
31f86b7
0ac6fb5
17a1bf7
7ffd051
9621fb0
743afcf
a2ba4fe
89ab1ff
b04b750
dfe900f
3e864fd
46bc9c5
aace011
c9db83e
11fb13f
bf23318
cfd8a90
d2fd944
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,10 +17,12 @@ | |
package healthcheck | ||
|
||
import ( | ||
"context" | ||
h "github.com/InVisionApp/go-health" | ||
"github.com/Peripli/service-manager/pkg/health" | ||
"github.com/Peripli/service-manager/pkg/util" | ||
"net/http" | ||
"strings" | ||
|
||
"github.com/Peripli/service-manager/pkg/log" | ||
"github.com/Peripli/service-manager/pkg/web" | ||
|
@@ -46,7 +48,7 @@ func (c *controller) healthCheck(r *web.Request) (*web.Response, error) { | |
logger := log.C(ctx) | ||
logger.Debugf("Performing health check...") | ||
healthState, _, _ := c.health.State() | ||
healthResult := c.aggregate(healthState) | ||
healthResult := c.aggregate(ctx, healthState) | ||
var status int | ||
if healthResult.Status == health.StatusUp { | ||
status = http.StatusOK | ||
|
@@ -56,7 +58,7 @@ func (c *controller) healthCheck(r *web.Request) (*web.Response, error) { | |
return util.NewJSONResponse(status, healthResult) | ||
} | ||
|
||
func (c *controller) aggregate(overallState map[string]h.State) *health.Health { | ||
func (c *controller) aggregate(ctx context.Context, overallState map[string]h.State) *health.Health { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "overall" suggests the state is already aggregated, better rename it |
||
if len(overallState) == 0 { | ||
return health.New().WithStatus(health.StatusUp) | ||
} | ||
|
@@ -70,6 +72,9 @@ func (c *controller) aggregate(overallState map[string]h.State) *health.Health { | |
details := make(map[string]interface{}) | ||
for name, state := range overallState { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why loop a second time over |
||
state.Status = convertStatus(state.Status) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why remap the status? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we decide to adopt library’s status “ok” and “failed” this change should be propagated everywhere since all the components check UP to determine if it is started correctly. |
||
if strings.Contains(name, health.PlatformIndicatorSuffix) && !web.IsAuthorized(ctx) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. avoid parsing strings as it is error prone, better store this data in a structured way There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not remove the details for all the health indicators in case the request is not authorised? |
||
state.Details = nil | ||
} | ||
details[name] = state | ||
} | ||
return health.New().WithStatus(overallStatus).WithDetails(details) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
* Copyright 2018 The Service Manager Authors | ||
* | ||
* 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. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package healthcheck | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/Peripli/service-manager/pkg/health" | ||
"github.com/Peripli/service-manager/pkg/query" | ||
"github.com/Peripli/service-manager/pkg/types" | ||
"github.com/Peripli/service-manager/storage" | ||
) | ||
|
||
// NewPlatformIndicator returns new health indicator for platforms of given type | ||
func NewPlatformIndicator(ctx context.Context, repository storage.Repository, platformType string) health.Indicator { | ||
return &platformIndicator{ | ||
ctx: ctx, | ||
repository: repository, | ||
platformType: platformType, | ||
} | ||
} | ||
|
||
type platformIndicator struct { | ||
repository storage.Repository | ||
ctx context.Context | ||
platformType string | ||
} | ||
|
||
// Name returns the name of the indicator | ||
func (pi *platformIndicator) Name() string { | ||
return pi.platformType + health.PlatformIndicatorSuffix // e.g. cf_platforms, k8s_platforms ... | ||
} | ||
|
||
// Status returns status of the health check | ||
func (pi *platformIndicator) Status() (interface{}, error) { | ||
typeCriteria := query.Criterion{ | ||
LeftOp: "type", | ||
Operator: query.EqualsOperator, | ||
RightOp: []string{pi.platformType}, | ||
Type: query.FieldQuery, | ||
} | ||
objList, err := pi.repository.List(pi.ctx, types.PlatformType, typeCriteria) | ||
if err != nil { | ||
return nil, fmt.Errorf("could not fetch platforms health from storage: %v", err) | ||
} | ||
|
||
details := make(map[string]interface{}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
for i := 0; i < objList.Len(); i++ { | ||
platform := objList.ItemAt(i).(*types.Platform) | ||
if platform.Active { | ||
details[platform.Name] = health.New().WithStatus(health.StatusUp) | ||
} else { | ||
details[platform.Name] = health.New().WithStatus(health.StatusDown).WithDetail("since", platform.LastActive) | ||
err = fmt.Errorf("there is inactive %s platforms", pi.platformType) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better include the total number of inactive platforms, e.g. "there are %d inactive %s platforms" |
||
} | ||
} | ||
return details, err | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* Copyright 2018 The Service Manager Authors | ||
* | ||
* 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. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package healthcheck | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"github.com/Peripli/service-manager/pkg/health" | ||
"github.com/Peripli/service-manager/pkg/types" | ||
storagefakes2 "github.com/Peripli/service-manager/storage/storagefakes" | ||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
"time" | ||
) | ||
|
||
var _ = Describe("Platforms Indicator", func() { | ||
var indicator health.Indicator | ||
var repository *storagefakes2.FakeStorage | ||
var platformType string | ||
var ctx context.Context | ||
var platform *types.Platform | ||
|
||
BeforeEach(func() { | ||
ctx = context.TODO() | ||
repository = &storagefakes2.FakeStorage{} | ||
platformType = "kubernetes" | ||
platform = &types.Platform{ | ||
Name: "test-platform", | ||
Type: platformType, | ||
Active: false, | ||
LastActive: time.Now(), | ||
} | ||
indicator = NewPlatformIndicator(ctx, repository, platformType) | ||
}) | ||
|
||
Context("Name", func() { | ||
It("should contain platform type in it", func() { | ||
Expect(indicator.Name()).Should(ContainSubstring(platformType)) | ||
}) | ||
}) | ||
|
||
Context("There is inactive platforms", func() { | ||
BeforeEach(func() { | ||
objectList := &types.Platforms{[]*types.Platform{platform}} | ||
repository.ListReturns(objectList, nil) | ||
}) | ||
It("should return error", func() { | ||
details, err := indicator.Status() | ||
health := details.(map[string]interface{})[platform.Name].(*health.Health) | ||
Expect(err).Should(HaveOccurred()) | ||
Expect(health.Details["since"]).ShouldNot(BeNil()) | ||
}) | ||
}) | ||
|
||
Context("Storage returns error", func() { | ||
var expectedErr error | ||
BeforeEach(func() { | ||
expectedErr = errors.New("storage err") | ||
repository.ListReturns(nil, expectedErr) | ||
}) | ||
It("should return error", func() { | ||
_, err := indicator.Status() | ||
Expect(err).Should(HaveOccurred()) | ||
Expect(err.Error()).To(ContainSubstring(expectedErr.Error())) | ||
}) | ||
}) | ||
|
||
Context("All platforms are active", func() { | ||
BeforeEach(func() { | ||
platform.Active = true | ||
objectList := &types.Platforms{[]*types.Platform{platform}} | ||
repository.ListReturns(objectList, nil) | ||
}) | ||
It("should not return error", func() { | ||
_, err := indicator.Status() | ||
Expect(err).ShouldNot(HaveOccurred()) | ||
}) | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
h
alias is too short for such a wide scope