Skip to content

Commit

Permalink
Merge POC into consul-k8s (#309)
Browse files Browse the repository at this point in the history
Merge POC into consul-k8s

Signed-off-by: Ashwin Venkatesh <ashwin@hashicorp.com>
Co-authored-by: Luke Kysow <1034429+lkysow@users.noreply.github.com>
  • Loading branch information
Ashwin Venkatesh and lkysow authored Aug 27, 2020
1 parent 2790a9c commit 55bd0f5
Show file tree
Hide file tree
Showing 49 changed files with 3,135 additions and 26 deletions.
55 changes: 53 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export GIT_DESCRIBE
export GOLDFLAGS
export GOTAGS


CRD_OPTIONS ?= "crd:trivialVersions=true"

################
# CI Variables #
Expand Down Expand Up @@ -79,7 +79,7 @@ else
DEV_PUSH_ARG=--no-push
endif

all: bin
all: bin ctrl-generate

bin:
@$(SHELL) $(CURDIR)/build-support/scripts/build-local.sh
Expand Down Expand Up @@ -128,6 +128,57 @@ clean:
$(CURDIR)/bin \
$(CURDIR)/pkg

# Run controller tests
ENVTEST_ASSETS_DIR=$(shell pwd)/testbin
ctrl-test: ctrl-generate ctrl-manifests
mkdir -p ${ENVTEST_ASSETS_DIR}
test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/master/hack/setup-envtest.sh
source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./...

# Deploy controller in the configured Kubernetes cluster in ~/.kube/config
ctrl-deploy: ctrl-manifests kustomize
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default | kubectl apply -f -

# Generate manifests e.g. CRD, RBAC etc.
ctrl-manifests: controller-gen
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases

# Generate code
ctrl-generate: controller-gen
$(CONTROLLER_GEN) object:headerFile="build-support/controller/boilerplate.go.txt" paths="./..."

# find or download controller-gen
# download controller-gen if necessary
controller-gen:
ifeq (, $(shell which controller-gen))
@{ \
set -e ;\
CONTROLLER_GEN_TMP_DIR=$$(mktemp -d) ;\
cd $$CONTROLLER_GEN_TMP_DIR ;\
go mod init tmp ;\
go get sigs.k8s.io/controller-tools/cmd/controller-gen@v0.3.0 ;\
rm -rf $$CONTROLLER_GEN_TMP_DIR ;\
}
CONTROLLER_GEN=$(GOBIN)/controller-gen
else
CONTROLLER_GEN=$(shell which controller-gen)
endif

kustomize:
ifeq (, $(shell which kustomize))
@{ \
set -e ;\
KUSTOMIZE_GEN_TMP_DIR=$$(mktemp -d) ;\
cd $$KUSTOMIZE_GEN_TMP_DIR ;\
go mod init tmp ;\
go get sigs.k8s.io/kustomize/kustomize/v3@v3.5.4 ;\
rm -rf $$KUSTOMIZE_GEN_TMP_DIR ;\
}
KUSTOMIZE=$(GOBIN)/kustomize
else
KUSTOMIZE=$(shell which kustomize)
endif

# In CircleCI, the linux binary will be attached from a previous step at pkg/bin/linux_amd64/. This make target
# should only run in CI and not locally.
Expand Down
7 changes: 7 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# this is a generated file used for operator sdk during code generation of CRDs, Controllers and webhooks
domain: hashicorp.com
layout: go.kubebuilder.io/v2
repo: github.com/hashicorp/consul-k8s
version: 3-alpha
plugins:
go.operator-sdk.io/v2-alpha: {}
20 changes: 20 additions & 0 deletions api/v1alpha1/groupversion_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Package v1alpha1 contains API Schema definitions for the consul.hashicorp.com v1alpha1 API group
// +kubebuilder:object:generate=true
// +groupName=consul.hashicorp.com
package v1alpha1

import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)

var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "consul.hashicorp.com", Version: "v1alpha1"}

// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}

// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)
139 changes: 139 additions & 0 deletions api/v1alpha1/servicedefaults_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package v1alpha1

import (
capi "github.com/hashicorp/consul/api"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// ServiceDefaultsSpec defines the desired state of ServiceDefaults
type ServiceDefaultsSpec struct {
Protocol string `json:"protocol,omitempty"`
MeshGateway MeshGatewayConfig `json:"meshGateway,omitempty"`
Expose ExposeConfig `json:"expose,omitempty"`
ExternalSNI string `json:"externalSNI,omitempty"`
}

// ServiceDefaultsStatus defines the observed state of ServiceDefaults
type ServiceDefaultsStatus struct {
Status `json:",inline"`
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// ServiceDefaults is the Schema for the servicedefaults API
// +kubebuilder:printcolumn:name="Synced",type="string",JSONPath=".status.conditions[?(@.type==\"Synced\")].status",description="The sync status of the resource with Consul"
type ServiceDefaults struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec ServiceDefaultsSpec `json:"spec,omitempty"`
Status ServiceDefaultsStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// ServiceDefaultsList contains a list of ServiceDefaults
type ServiceDefaultsList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ServiceDefaults `json:"items"`
}

func init() {
SchemeBuilder.Register(&ServiceDefaults{}, &ServiceDefaultsList{})
}

// ToConsul converts the entry into it's Consul equivalent struct.
func (s *ServiceDefaults) ToConsul() *capi.ServiceConfigEntry {
return &capi.ServiceConfigEntry{
Kind: capi.ServiceDefaults,
Name: s.Name,
//Namespace: s.Namespace, // todo: don't set this unless enterprise
Protocol: s.Spec.Protocol,
MeshGateway: s.Spec.MeshGateway.toConsul(),
Expose: s.Spec.Expose.toConsul(),
ExternalSNI: s.Spec.ExternalSNI,
}
}

// MatchesConsul returns true if entry has the same config as this struct.
func (s *ServiceDefaults) MatchesConsul(entry *capi.ServiceConfigEntry) bool {
return s.Name == entry.GetName() &&
s.Spec.Protocol == entry.Protocol &&
s.Spec.MeshGateway.Mode == string(entry.MeshGateway.Mode) &&
s.Spec.Expose.matches(entry.Expose) &&
s.Spec.ExternalSNI == entry.ExternalSNI
}

// ExposeConfig describes HTTP paths to expose through Envoy outside of Connect.
// Users can expose individual paths and/or all HTTP/GRPC paths for checks.
type ExposeConfig struct {
// Checks defines whether paths associated with Consul checks will be exposed.
// This flag triggers exposing all HTTP and GRPC check paths registered for the service.
Checks bool `json:"checks,omitempty"`

// Paths is the list of paths exposed through the proxy.
Paths []ExposePath `json:"paths,omitempty"`
}

type ExposePath struct {
// ListenerPort defines the port of the proxy's listener for exposed paths.
ListenerPort int `json:"listenerPort,omitempty"`

// Path is the path to expose through the proxy, ie. "/metrics."
Path string `json:"path,omitempty"`

// LocalPathPort is the port that the service is listening on for the given path.
LocalPathPort int `json:"localPathPort,omitempty"`

// Protocol describes the upstream's service protocol.
// Valid values are "http" and "http2", defaults to "http"
Protocol string `json:"protocol,omitempty"`
}

// matches returns true if the expose config of the entry is the same as the struct
func (e ExposeConfig) matches(expose capi.ExposeConfig) bool {
if e.Checks != expose.Checks {
return false
}

if len(e.Paths) != len(expose.Paths) {
return false
}

for _, path := range e.Paths {
found := false
for _, entryPath := range expose.Paths {
if path.Protocol == entryPath.Protocol &&
path.Path == entryPath.Path &&
path.ListenerPort == entryPath.ListenerPort &&
path.LocalPathPort == entryPath.LocalPathPort {
found = true
break
}
}

if !found {
return false
}
}
return true
}

// toConsul returns the ExposeConfig for the entry
func (e ExposeConfig) toConsul() capi.ExposeConfig {
var paths []capi.ExposePath
for _, path := range e.Paths {
paths = append(paths, capi.ExposePath{
ListenerPort: path.ListenerPort,
Path: path.Path,
LocalPathPort: path.LocalPathPort,
Protocol: path.Protocol,
})
}
return capi.ExposeConfig{
Checks: e.Checks,
Paths: paths,
}
}
Loading

0 comments on commit 55bd0f5

Please sign in to comment.