Skip to content

Commit

Permalink
add status package with tests and check-status cmd
Browse files Browse the repository at this point in the history
includes makefile and dockerfile changes for check-status

Signed-off-by: derek mcquay <[email protected]>
  • Loading branch information
dmmcquay committed Jul 12, 2018
1 parent 89743f8 commit 6feb62d
Show file tree
Hide file tree
Showing 9 changed files with 396 additions and 2 deletions.
1 change: 1 addition & 0 deletions Dockerfile.amd64
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ FROM amd64/alpine:3.7
LABEL maintainer "Casey Davenport <[email protected]>"

ADD bin/kube-controllers-linux-amd64 /usr/bin/kube-controllers
ADD bin/check-status-linux-amd64 /usr/bin/check-status
ENTRYPOINT ["/usr/bin/kube-controllers"]
1 change: 1 addition & 0 deletions Dockerfile.arm64
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ FROM arm64v8/alpine:3.7
LABEL maintainer "Casey Davenport <[email protected]>"

ADD bin/kube-controllers-linux-amd64 /usr/bin/kube-controllers
ADD bin/check-status-linux-amd64 /usr/bin/check-status
ENTRYPOINT ["/usr/bin/kube-controllers"]
1 change: 1 addition & 0 deletions Dockerfile.ppc64le
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ FROM ppc64le/alpine:3.7
LABEL maintainer "Casey Davenport <[email protected]>"

ADD bin/kube-controllers-linux-ppc64le /usr/bin/kube-controllers
ADD bin/check-status-linux-ppc64le /usr/bin/check-status
ENTRYPOINT ["/usr/bin/kube-controllers"]
1 change: 1 addition & 0 deletions Dockerfile.s390x
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ FROM s390x/alpine:3.7
LABEL maintainer "LoZ Open Source Ecosystem (https://www.ibm.com/developerworks/community/groups/community/lozopensource)"

ADD bin/kube-controllers-linux-s390x /usr/bin/kube-controllers
ADD bin/check-status-linux-s390x /usr/bin/check-status
ENTRYPOINT ["/usr/bin/kube-controllers"]
18 changes: 16 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ clean:
###############################################################################
# Building the binary
###############################################################################
build: bin/kube-controllers-linux-$(ARCH)
build: bin/kube-controllers-linux-$(ARCH) bin/check-status-linux-$(ARCH)
build-all: $(addprefix sub-build-,$(ARCHES))
sub-build-%:
$(MAKE) build ARCH=$*
Expand Down Expand Up @@ -114,7 +114,20 @@ bin/kube-controllers-linux-$(ARCH): vendor $(SRCFILES)
-e LOCAL_USER_ID=$(LOCAL_USER_ID) \
-v $(CURDIR)/.go-pkg-cache:/go-cache/:rw \
-e GOCACHE=/go-cache \
$(CALICO_BUILD) go build -v -o bin/kube-controllers-$(OS)-$(ARCH) -ldflags "-X main.VERSION=$(GIT_VERSION)" ./cmd/kube-controllers/
$(CALICO_BUILD) go build -v -o bin/kube-controllers-$(OS)-$(ARCH) -ldflags "-X main.VERSION=$(GIT_VERSION)" ./cmd/kube-controllers/

bin/check-status-linux-$(ARCH): vendor $(SRCFILES)
mkdir -p bin
-mkdir -p .go-pkg-cache
docker run --rm \
-e GOOS=$(OS) -e GOARCH=$(ARCH) \
-v $(CURDIR):/go/src/$(PACKAGE_NAME):ro \
-v $(CURDIR)/bin:/go/src/$(PACKAGE_NAME)/bin \
-w /go/src/$(PACKAGE_NAME) \
-e LOCAL_USER_ID=$(LOCAL_USER_ID) \
-v $(CURDIR)/.go-pkg-cache:/go-cache/:rw \
-e GOCACHE=/go-cache \
$(CALICO_BUILD) go build -v -o bin/check-status-$(OS)-$(ARCH) -ldflags "-X main.VERSION=$(GIT_VERSION)" ./cmd/check-status/

###############################################################################
# Building the image
Expand Down Expand Up @@ -186,6 +199,7 @@ static-checks: vendor check-copyright
fix goimports:
goimports -l -w ./pkg
goimports -l -w ./cmd/kube-controllers/main.go
goimports -l -w ./cmd/check-status/main.go

.PHONY: install-git-hooks
## Install Git hooks
Expand Down
79 changes: 79 additions & 0 deletions cmd/check-status/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) 2017 Tigera, Inc. All rights reserved.
//
// 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 main

import (
"flag"
"fmt"
"os"
"time"

"github.com/projectcalico/kube-controllers/pkg/status"
)

// VERSION is filled out during the build process (using git describe output)
var VERSION string

// main is the main entry point into the anx controller.
func main() {

// If `-v` is passed, display the version and exit.
// Use a new flag set so as not to conflict with existing libraries which use "flag"
flagSet := flag.NewFlagSet("check-status", flag.ExitOnError)
version := flagSet.Bool("v", false, "Display version")
file := flagSet.String("f", status.DefaultStatusFile, "File to read with status information")
checkReady := flagSet.Bool("r", false, "Check readiness")
err := flagSet.Parse(os.Args[1:])
if err != nil {
fmt.Println("Failed to parse flags")
os.Exit(1)
}
if *version {
fmt.Println(VERSION)
os.Exit(0)
}

// Read the status file
if *checkReady {
var st *status.Status
var err error
// Try reading the status file up to 3 times.
for i := 0; i < 3; i++ {
st, err = status.ReadStatusFile(*file)
if err != nil {
time.Sleep(1 * time.Second)
continue
}
break
}
if err != nil {
fmt.Printf("Failed to read status file %s: %v\n", *file, err)
os.Exit(1)
}

// Check if all components are ready
if st.GetReadiness() {
fmt.Println("Ready")
os.Exit(0)
}

// If not ready, log the components that are not ready
fmt.Println(st.GetNotReadyConditions())
os.Exit(1)
}

fmt.Println("No command specified to check-status")
os.Exit(1)
}
142 changes: 142 additions & 0 deletions pkg/status/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// Copyright (c) 2017 Tigera, Inc. All rights reserved.
//
// 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 status

import (
"encoding/json"
"io/ioutil"
"strings"
"sync"

"github.com/sirupsen/logrus"
)

const (
DefaultStatusFile string = "status.json"
)

type ConditionStatus struct {
Ready bool
Reason string
}

type Status struct {
Readiness map[string]ConditionStatus
readyMutex sync.Mutex
statusFile string
}

func New(file string) *Status {
st := Status{
statusFile: file,
Readiness: map[string]ConditionStatus{},
}
return &st
}

// SetReady sets the status of one ready key and the reason associated with
// that status.
func (s *Status) SetReady(key string, val bool, reason string) {
needUpdate := false
s.readyMutex.Lock()
if prev, ok := s.Readiness[key]; !ok {
needUpdate = true
} else if prev.Ready != val || prev.Reason != reason {
needUpdate = true
}
s.Readiness[key] = ConditionStatus{Ready: val, Reason: reason}
s.readyMutex.Unlock()
if needUpdate {
_ = s.WriteStatus()
}
}

// GetReady check the status of the specified ready key, if the key has never
// been set then it is considered not ready (false).
func (s *Status) GetReady(key string) bool {
s.readyMutex.Lock()
defer s.readyMutex.Unlock()
v, ok := s.Readiness[key]
if !ok {
return false
}
return v.Ready
}

// GetReadiness checks all readiness keys and returns true if all are ready.
// If there are no readiness conditions then it has not been initialized and
// is considered not ready.
func (s *Status) GetReadiness() bool {
s.readyMutex.Lock()
defer s.readyMutex.Unlock()

if len(s.Readiness) == 0 {
return false
}
for _, v := range s.Readiness {
if !v.Ready {
return false
}
}
return true
}

// GetNotReadyConditions cycles through all readiness keys and for any that
// are not ready the reasons are combined and returned.
// The output format is '<reason 1>; <reason 2>'.
func (s *Status) GetNotReadyConditions() string {
var unready []string
s.readyMutex.Lock()
defer s.readyMutex.Unlock()
for _, v := range s.Readiness {
if !v.Ready {
unready = append(unready, v.Reason)
}
}
return strings.Join(unready, "; ")

}

// WriteStatus writes out the status in json format.
func (c *Status) WriteStatus() error {
b, err := json.Marshal(*c)
if err != nil {
logrus.Errorf("Failed to marshal readiness: %s", err)
return err
}

err = ioutil.WriteFile(c.statusFile, b, 0644)
if err != nil {
logrus.Errorf("Failed to write readiness file: %s", err)
return err
}

return nil
}

// ReadStatusFile reads in the status file as written by WriteStatus.
func ReadStatusFile(file string) (*Status, error) {
st := Status{}
contents, err := ioutil.ReadFile(file)
if err != nil {
return nil, err
}
err = json.Unmarshal(contents, &st)
if err != nil {
return nil, err
}

return &st, nil
}
27 changes: 27 additions & 0 deletions pkg/status/status_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) 2017 Tigera, Inc. All rights reserved.
//
// 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 status_test

import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

"testing"
)

func TestConfig(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "pkg/status suite")
}
Loading

0 comments on commit 6feb62d

Please sign in to comment.