20
Makefile
20
Makefile
@@ -39,7 +39,7 @@ define ALL_HELP_INFO
|
||||
# debugging tools like delve.
|
||||
endef
|
||||
.PHONY: all
|
||||
all: test ks-apiserver ks-apigateway ks-iam controller-manager
|
||||
all: test ks-apiserver ks-apigateway ks-iam controller-manager generate-apis
|
||||
|
||||
# Build ks-apiserver binary
|
||||
ks-apiserver: test
|
||||
@@ -58,39 +58,37 @@ controller-manager: test
|
||||
hack/gobuild.sh cmd/controller-manager
|
||||
|
||||
# Run go fmt against code
|
||||
fmt:
|
||||
fmt: generate-apis
|
||||
go fmt ./pkg/... ./cmd/...
|
||||
|
||||
# Run go vet against code
|
||||
vet:
|
||||
vet: generate-apis
|
||||
go vet ./pkg/... ./cmd/...
|
||||
|
||||
# Generate manifests e.g. CRD, RBAC etc.
|
||||
manifests:
|
||||
go run vendor/sigs.k8s.io/controller-tools/cmd/controller-gen/main.go all
|
||||
|
||||
crds:
|
||||
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./pkg/apis/network/..." output:crd:artifacts:config=config/crd/bases
|
||||
crds: generate-apis
|
||||
$(CONTROLLER_GEN) crd:trivialVersions=true paths="./pkg/apis/devops/..." output:crd:artifacts:config=config/crds
|
||||
|
||||
deploy: manifests
|
||||
kubectl apply -f config/crds
|
||||
kustomize build config/default | kubectl apply -f -
|
||||
|
||||
# Generate DeepCopy to implement runtime.Object
|
||||
deepcopy:
|
||||
./vendor/k8s.io/code-generator/generate-groups.sh all kubesphere.io/kubesphere/pkg/client kubesphere.io/kubesphere/pkg/apis "servicemesh:v1alpha2 tenant:v1alpha1"
|
||||
|
||||
generate:
|
||||
generate: crds
|
||||
go generate ./pkg/... ./cmd/...
|
||||
# Generate code
|
||||
generate-apis: controller-gen
|
||||
$(CONTROLLER_GEN) object:headerFile=./hack/boilerplate.go.txt paths=./pkg/apis/...
|
||||
|
||||
|
||||
# Build the docker image
|
||||
docker-build: all
|
||||
docker build . -t ${IMG}
|
||||
|
||||
# Run tests
|
||||
test: generate fmt vet
|
||||
test: generate fmt vet generate-apis
|
||||
go test ./pkg/... ./cmd/... -coverprofile cover.out
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
394
config/crds/devops.kubesphere.io_s2ibinaries.yaml
Normal file
394
config/crds/devops.kubesphere.io_s2ibinaries.yaml
Normal file
@@ -0,0 +1,394 @@
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: s2ibinaries.devops.kubesphere.io
|
||||
spec:
|
||||
additionalPrinterColumns:
|
||||
- JSONPath: .spec.fileName
|
||||
name: FileName
|
||||
type: string
|
||||
- JSONPath: .spec.md5
|
||||
name: MD5
|
||||
type: string
|
||||
- JSONPath: .spec.size
|
||||
name: Size
|
||||
type: string
|
||||
- JSONPath: .status.phase
|
||||
name: Phase
|
||||
type: string
|
||||
group: devops.kubesphere.io
|
||||
names:
|
||||
kind: S2iBinary
|
||||
plural: s2ibinaries
|
||||
scope: ""
|
||||
subresources: {}
|
||||
validation:
|
||||
openAPIV3Schema:
|
||||
description: S2iBinary is the Schema for the s2ibinaries API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: 'Annotations is an unstructured key value map stored with
|
||||
a resource that may be set by external tools to store and retrieve
|
||||
arbitrary metadata. They are not queryable and should be preserved
|
||||
when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations'
|
||||
type: object
|
||||
clusterName:
|
||||
description: The name of the cluster which the object belongs to. This
|
||||
is used to distinguish resources with same name and namespace in different
|
||||
clusters. This field is not set anywhere right now and apiserver is
|
||||
going to ignore it if set in create or update request.
|
||||
type: string
|
||||
creationTimestamp:
|
||||
description: "CreationTimestamp is a timestamp representing the server
|
||||
time when this object was created. It is not guaranteed to be set
|
||||
in happens-before order across separate operations. Clients may not
|
||||
set this value. It is represented in RFC3339 form and is in UTC. \n
|
||||
Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
|
||||
format: date-time
|
||||
type: string
|
||||
deletionGracePeriodSeconds:
|
||||
description: Number of seconds allowed for this object to gracefully
|
||||
terminate before it will be removed from the system. Only set when
|
||||
deletionTimestamp is also set. May only be shortened. Read-only.
|
||||
format: int64
|
||||
type: integer
|
||||
deletionTimestamp:
|
||||
description: "DeletionTimestamp is RFC 3339 date and time at which this
|
||||
resource will be deleted. This field is set by the server when a graceful
|
||||
deletion is requested by the user, and is not directly settable by
|
||||
a client. The resource is expected to be deleted (no longer visible
|
||||
from resource lists, and not reachable by name) after the time in
|
||||
this field, once the finalizers list is empty. As long as the finalizers
|
||||
list contains items, deletion is blocked. Once the deletionTimestamp
|
||||
is set, this value may not be unset or be set further into the future,
|
||||
although it may be shortened or the resource may be deleted prior
|
||||
to this time. For example, a user may request that a pod is deleted
|
||||
in 30 seconds. The Kubelet will react by sending a graceful termination
|
||||
signal to the containers in the pod. After that 30 seconds, the Kubelet
|
||||
will send a hard termination signal (SIGKILL) to the container and
|
||||
after cleanup, remove the pod from the API. In the presence of network
|
||||
partitions, this object may still exist after this timestamp, until
|
||||
an administrator or automated process can determine the resource is
|
||||
fully terminated. If not set, graceful deletion of the object has
|
||||
not been requested. \n Populated by the system when a graceful deletion
|
||||
is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
|
||||
format: date-time
|
||||
type: string
|
||||
finalizers:
|
||||
description: Must be empty before the object is deleted from the registry.
|
||||
Each entry is an identifier for the responsible component that will
|
||||
remove the entry from the list. If the deletionTimestamp of the object
|
||||
is non-nil, entries in this list can only be removed.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
generateName:
|
||||
description: "GenerateName is an optional prefix, used by the server,
|
||||
to generate a unique name ONLY IF the Name field has not been provided.
|
||||
If this field is used, the name returned to the client will be different
|
||||
than the name passed. This value will also be combined with a unique
|
||||
suffix. The provided value has the same validation rules as the Name
|
||||
field, and may be truncated by the length of the suffix required to
|
||||
make the value unique on the server. \n If this field is specified
|
||||
and the generated name exists, the server will NOT return a 409 -
|
||||
instead, it will either return 201 Created or 500 with Reason ServerTimeout
|
||||
indicating a unique name could not be found in the time allotted,
|
||||
and the client should retry (optionally after the time indicated in
|
||||
the Retry-After header). \n Applied only if Name is not specified.
|
||||
More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency"
|
||||
type: string
|
||||
generation:
|
||||
description: A sequence number representing a specific generation of
|
||||
the desired state. Populated by the system. Read-only.
|
||||
format: int64
|
||||
type: integer
|
||||
initializers:
|
||||
description: "An initializer is a controller which enforces some system
|
||||
invariant at object creation time. This field is a list of initializers
|
||||
that have not yet acted on this object. If nil or empty, this object
|
||||
has been completely initialized. Otherwise, the object is considered
|
||||
uninitialized and is hidden (in list/watch and get calls) from clients
|
||||
that haven't explicitly asked to observe uninitialized objects. \n
|
||||
When an object is created, the system will populate this list with
|
||||
the current set of initializers. Only privileged users may set or
|
||||
modify this list. Once it is empty, it may not be modified further
|
||||
by any user."
|
||||
properties:
|
||||
pending:
|
||||
description: Pending is a list of initializers that must execute
|
||||
in order before this object is visible. When the last pending
|
||||
initializer is removed, and no failing result is set, the initializers
|
||||
struct will be set to nil and the object is considered as initialized
|
||||
and visible to all clients.
|
||||
items:
|
||||
properties:
|
||||
name:
|
||||
description: name of the process that is responsible for initializing
|
||||
this object.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: array
|
||||
result:
|
||||
description: If result is set with the Failure field, the object
|
||||
will be persisted to storage and then deleted, ensuring that other
|
||||
clients can observe the deletion.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this
|
||||
representation of an object. Servers should convert recognized
|
||||
schemas to the latest internal value, and may reject unrecognized
|
||||
values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources'
|
||||
type: string
|
||||
code:
|
||||
description: Suggested HTTP return code for this status, 0 if
|
||||
not set.
|
||||
format: int32
|
||||
type: integer
|
||||
details:
|
||||
description: Extended data associated with the reason. Each
|
||||
reason may define its own extended details. This field is
|
||||
optional and the data returned is not guaranteed to conform
|
||||
to any schema except that defined by the reason type.
|
||||
properties:
|
||||
causes:
|
||||
description: The Causes array includes more details associated
|
||||
with the StatusReason failure. Not all StatusReasons may
|
||||
provide detailed causes.
|
||||
items:
|
||||
properties:
|
||||
field:
|
||||
description: "The field of the resource that has caused
|
||||
this error, as named by its JSON serialization.
|
||||
May include dot and postfix notation for nested
|
||||
attributes. Arrays are zero-indexed. Fields may
|
||||
appear more than once in an array of causes due
|
||||
to fields having multiple errors. Optional. \n Examples:
|
||||
\ \"name\" - the field \"name\" on the current
|
||||
resource \"items[0].name\" - the field \"name\"
|
||||
on the first array entry in \"items\""
|
||||
type: string
|
||||
message:
|
||||
description: A human-readable description of the cause
|
||||
of the error. This field may be presented as-is
|
||||
to a reader.
|
||||
type: string
|
||||
reason:
|
||||
description: A machine-readable description of the
|
||||
cause of the error. If this value is empty there
|
||||
is no information available.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
group:
|
||||
description: The group attribute of the resource associated
|
||||
with the status StatusReason.
|
||||
type: string
|
||||
kind:
|
||||
description: 'The kind attribute of the resource associated
|
||||
with the status StatusReason. On some operations may differ
|
||||
from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
name:
|
||||
description: The name attribute of the resource associated
|
||||
with the status StatusReason (when there is a single name
|
||||
which can be described).
|
||||
type: string
|
||||
retryAfterSeconds:
|
||||
description: If specified, the time in seconds before the
|
||||
operation should be retried. Some errors may indicate
|
||||
the client must take an alternate action - for those errors
|
||||
this field may indicate how long to wait before taking
|
||||
the alternate action.
|
||||
format: int32
|
||||
type: integer
|
||||
uid:
|
||||
description: 'UID of the resource. (when there is a single
|
||||
resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
|
||||
type: string
|
||||
type: object
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource
|
||||
this object represents. Servers may infer this from the endpoint
|
||||
the client submits requests to. Cannot be updated. In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
message:
|
||||
description: A human-readable description of the status of this
|
||||
operation.
|
||||
type: string
|
||||
metadata:
|
||||
description: 'Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
|
||||
properties:
|
||||
continue:
|
||||
description: continue may be set if the user set a limit
|
||||
on the number of items returned, and indicates that the
|
||||
server has more data available. The value is opaque and
|
||||
may be used to issue another request to the endpoint that
|
||||
served this list to retrieve the next set of available
|
||||
objects. Continuing a consistent list may not be possible
|
||||
if the server configuration has changed or more than a
|
||||
few minutes have passed. The resourceVersion field returned
|
||||
when using this continue value will be identical to the
|
||||
value in the first response, unless you have received
|
||||
this token from an error message.
|
||||
type: string
|
||||
resourceVersion:
|
||||
description: 'String that identifies the server''s internal
|
||||
version of this object that can be used by clients to
|
||||
determine when objects have changed. Value must be treated
|
||||
as opaque by clients and passed unmodified back to the
|
||||
server. Populated by the system. Read-only. More info:
|
||||
https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency'
|
||||
type: string
|
||||
selfLink:
|
||||
description: selfLink is a URL representing this object.
|
||||
Populated by the system. Read-only.
|
||||
type: string
|
||||
type: object
|
||||
reason:
|
||||
description: A machine-readable description of why this operation
|
||||
is in the "Failure" status. If this value is empty there is
|
||||
no information available. A Reason clarifies an HTTP status
|
||||
code but does not override it.
|
||||
type: string
|
||||
status:
|
||||
description: 'Status of the operation. One of: "Success" or
|
||||
"Failure". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status'
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- pending
|
||||
type: object
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: 'Map of string keys and values that can be used to organize
|
||||
and categorize (scope and select) objects. May match selectors of
|
||||
replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels'
|
||||
type: object
|
||||
name:
|
||||
description: 'Name must be unique within a namespace. Is required when
|
||||
creating resources, although some resources may allow a client to
|
||||
request the generation of an appropriate name automatically. Name
|
||||
is primarily intended for creation idempotence and configuration definition.
|
||||
Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
|
||||
type: string
|
||||
namespace:
|
||||
description: "Namespace defines the space within each name must be unique.
|
||||
An empty namespace is equivalent to the \"default\" namespace, but
|
||||
\"default\" is the canonical representation. Not all objects are required
|
||||
to be scoped to a namespace - the value of this field for those objects
|
||||
will be empty. \n Must be a DNS_LABEL. Cannot be updated. More info:
|
||||
http://kubernetes.io/docs/user-guide/namespaces"
|
||||
type: string
|
||||
ownerReferences:
|
||||
description: List of objects depended by this object. If ALL objects
|
||||
in the list have been deleted, this object will be garbage collected.
|
||||
If this object is managed by a controller, then an entry in this list
|
||||
will point to this controller, with the controller field set to true.
|
||||
There cannot be more than one managing controller.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: API version of the referent.
|
||||
type: string
|
||||
blockOwnerDeletion:
|
||||
description: If true, AND if the owner has the "foregroundDeletion"
|
||||
finalizer, then the owner cannot be deleted from the key-value
|
||||
store until this reference is removed. Defaults to false. To
|
||||
set this field, a user needs "delete" permission of the owner,
|
||||
otherwise 422 (Unprocessable Entity) will be returned.
|
||||
type: boolean
|
||||
controller:
|
||||
description: If true, this reference points to the managing controller.
|
||||
type: boolean
|
||||
kind:
|
||||
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
name:
|
||||
description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
|
||||
type: string
|
||||
uid:
|
||||
description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
|
||||
type: string
|
||||
required:
|
||||
- apiVersion
|
||||
- kind
|
||||
- name
|
||||
- uid
|
||||
type: object
|
||||
type: array
|
||||
resourceVersion:
|
||||
description: "An opaque value that represents the internal version of
|
||||
this object that can be used by clients to determine when objects
|
||||
have changed. May be used for optimistic concurrency, change detection,
|
||||
and the watch operation on a resource or set of resources. Clients
|
||||
must treat these values as opaque and passed unmodified back to the
|
||||
server. They may only be valid for a particular resource or set of
|
||||
resources. \n Populated by the system. Read-only. Value must be treated
|
||||
as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency"
|
||||
type: string
|
||||
selfLink:
|
||||
description: SelfLink is a URL representing this object. Populated by
|
||||
the system. Read-only.
|
||||
type: string
|
||||
uid:
|
||||
description: "UID is the unique in time and space value for this object.
|
||||
It is typically generated by the server on successful creation of
|
||||
a resource and is not allowed to change on PUT operations. \n Populated
|
||||
by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids"
|
||||
type: string
|
||||
type: object
|
||||
spec:
|
||||
properties:
|
||||
downloadURL:
|
||||
description: DownloadURL in KubeSphere
|
||||
type: string
|
||||
fileName:
|
||||
description: FileName is filename of binary
|
||||
type: string
|
||||
md5:
|
||||
description: MD5 is Binary's MD5 Hash
|
||||
type: string
|
||||
size:
|
||||
description: Size is the file size of file
|
||||
type: string
|
||||
uploadTimeStamp:
|
||||
description: UploadTime is last upload time
|
||||
format: date-time
|
||||
type: string
|
||||
type: object
|
||||
status:
|
||||
properties:
|
||||
phase:
|
||||
description: Phase is status of S2iBinary . Possible value is "Ready","UnableToDownload"
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
26
pkg/apis/addtoscheme_devops_v1alpha1.go
Normal file
26
pkg/apis/addtoscheme_devops_v1alpha1.go
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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 apis
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
|
||||
AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme)
|
||||
}
|
||||
18
pkg/apis/devops/group.go
Normal file
18
pkg/apis/devops/group.go
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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 devops contains devops API versions
|
||||
package devops
|
||||
23
pkg/apis/devops/v1alpha1/doc.go
Normal file
23
pkg/apis/devops/v1alpha1/doc.go
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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 v1alpha1 contains API Schema definitions for the devops v1alpha1 API group
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package,register
|
||||
// +k8s:conversion-gen=kubesphere.io/kubesphere/pkg/apis/devops
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=devops.kubesphere.io
|
||||
package v1alpha1
|
||||
46
pkg/apis/devops/v1alpha1/register.go
Normal file
46
pkg/apis/devops/v1alpha1/register.go
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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.
|
||||
*/
|
||||
|
||||
// NOTE: Boilerplate only. Ignore this file.
|
||||
|
||||
// Package v1alpha1 contains API Schema definitions for the devops v1alpha1 API group
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package,register
|
||||
// +k8s:conversion-gen=kubesphere.io/kubesphere/pkg/apis/devops
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=devops.kubesphere.io
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"sigs.k8s.io/controller-runtime/pkg/runtime/scheme"
|
||||
)
|
||||
|
||||
var (
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
SchemeGroupVersion = schema.GroupVersion{Group: "devops.kubesphere.io", Version: "v1alpha1"}
|
||||
|
||||
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
|
||||
SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
|
||||
|
||||
// AddToScheme is required by pkg/client/...
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// Resource is required by pkg/client/listers/...
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
74
pkg/apis/devops/v1alpha1/s2ibinary_types.go
Normal file
74
pkg/apis/devops/v1alpha1/s2ibinary_types.go
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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 v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||
|
||||
// S2iBinarySpec defines the desired state of S2iBinary
|
||||
type S2iBinarySpec struct {
|
||||
//FileName is filename of binary
|
||||
FileName string `json:"fileName,omitempty"`
|
||||
//MD5 is Binary's MD5 Hash
|
||||
MD5 string `json:"md5,omitempty"`
|
||||
//Size is the file size of file
|
||||
Size string `json:"size,omitempty"`
|
||||
//DownloadURL in KubeSphere
|
||||
DownloadURL string `json:"downloadURL,omitempty"`
|
||||
// UploadTime is last upload time
|
||||
UploadTimeStamp metav1.Time `json:"uploadTimeStamp,omitempty"`
|
||||
}
|
||||
|
||||
// S2iBinaryStatus defines the observed state of S2iBinary
|
||||
type S2iBinaryStatus struct {
|
||||
//Phase is status of S2iBinary . Possible value is "Ready","UnableToDownload"
|
||||
Phase string `json:"phase,omitempty"`
|
||||
}
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// S2iBinary is the Schema for the s2ibinaries API
|
||||
// +k8s:openapi-gen=true
|
||||
// +kubebuilder:printcolumn:name="FileName",type="string",JSONPath=".spec.fileName"
|
||||
// +kubebuilder:printcolumn:name="MD5",type="string",JSONPath=".spec.md5"
|
||||
// +kubebuilder:printcolumn:name="Size",type="string",JSONPath=".spec.size"
|
||||
// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase"
|
||||
type S2iBinary struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec S2iBinarySpec `json:"spec,omitempty"`
|
||||
Status S2iBinaryStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// S2iBinaryList contains a list of S2iBinary
|
||||
type S2iBinaryList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []S2iBinary `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&S2iBinary{}, &S2iBinaryList{})
|
||||
}
|
||||
58
pkg/apis/devops/v1alpha1/s2ibinary_types_test.go
Normal file
58
pkg/apis/devops/v1alpha1/s2ibinary_types_test.go
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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 v1alpha1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/onsi/gomega"
|
||||
"golang.org/x/net/context"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
func TestStorageS2iBinary(t *testing.T) {
|
||||
key := types.NamespacedName{
|
||||
Name: "foo",
|
||||
Namespace: "default",
|
||||
}
|
||||
created := &S2iBinary{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
Namespace: "default",
|
||||
}}
|
||||
g := gomega.NewGomegaWithT(t)
|
||||
|
||||
// Test Create
|
||||
fetched := &S2iBinary{}
|
||||
g.Expect(c.Create(context.TODO(), created)).NotTo(gomega.HaveOccurred())
|
||||
|
||||
g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred())
|
||||
g.Expect(fetched).To(gomega.Equal(created))
|
||||
|
||||
// Test Updating the Labels
|
||||
updated := fetched.DeepCopy()
|
||||
updated.Labels = map[string]string{"hello": "world"}
|
||||
g.Expect(c.Update(context.TODO(), updated)).NotTo(gomega.HaveOccurred())
|
||||
|
||||
g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred())
|
||||
g.Expect(fetched).To(gomega.Equal(updated))
|
||||
|
||||
// Test Delete
|
||||
g.Expect(c.Delete(context.TODO(), fetched)).NotTo(gomega.HaveOccurred())
|
||||
g.Expect(c.Get(context.TODO(), key, fetched)).To(gomega.HaveOccurred())
|
||||
}
|
||||
55
pkg/apis/devops/v1alpha1/v1alpha1_suite_test.go
Normal file
55
pkg/apis/devops/v1alpha1/v1alpha1_suite_test.go
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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 v1alpha1
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/envtest"
|
||||
)
|
||||
|
||||
var cfg *rest.Config
|
||||
var c client.Client
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
t := &envtest.Environment{
|
||||
CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "..", "config", "crds")},
|
||||
}
|
||||
|
||||
err := SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if cfg, err = t.Start(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if c, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
code := m.Run()
|
||||
t.Stop()
|
||||
os.Exit(code)
|
||||
}
|
||||
115
pkg/apis/devops/v1alpha1/zz_generated.deepcopy.go
Normal file
115
pkg/apis/devops/v1alpha1/zz_generated.deepcopy.go
Normal file
@@ -0,0 +1,115 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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.
|
||||
*/
|
||||
|
||||
// autogenerated by controller-gen object, do not modify manually
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBinary) DeepCopyInto(out *S2iBinary) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
out.Status = in.Status
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBinary.
|
||||
func (in *S2iBinary) DeepCopy() *S2iBinary {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBinary)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *S2iBinary) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBinaryList) DeepCopyInto(out *S2iBinaryList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]S2iBinary, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBinaryList.
|
||||
func (in *S2iBinaryList) DeepCopy() *S2iBinaryList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBinaryList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *S2iBinaryList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBinarySpec) DeepCopyInto(out *S2iBinarySpec) {
|
||||
*out = *in
|
||||
in.UploadTimeStamp.DeepCopyInto(&out.UploadTimeStamp)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBinarySpec.
|
||||
func (in *S2iBinarySpec) DeepCopy() *S2iBinarySpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBinarySpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBinaryStatus) DeepCopyInto(out *S2iBinaryStatus) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBinaryStatus.
|
||||
func (in *S2iBinaryStatus) DeepCopy() *S2iBinaryStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBinaryStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
@@ -63,13 +63,6 @@ func (in *WorkspaceNetworkPolicyEgressRule) DeepCopyInto(out *WorkspaceNetworkPo
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.To != nil {
|
||||
in, out := &in.To, &out.To
|
||||
*out = make([]WorkspaceNetworkPolicyPeer, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicyEgressRule.
|
||||
@@ -92,13 +85,6 @@ func (in *WorkspaceNetworkPolicyIngressRule) DeepCopyInto(out *WorkspaceNetworkP
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.From != nil {
|
||||
in, out := &in.From, &out.From
|
||||
*out = make([]WorkspaceNetworkPolicyPeer, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicyIngressRule.
|
||||
@@ -172,20 +158,6 @@ func (in *WorkspaceNetworkPolicySpec) DeepCopyInto(out *WorkspaceNetworkPolicySp
|
||||
*out = make([]v1.PolicyType, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Ingress != nil {
|
||||
in, out := &in.Ingress, &out.Ingress
|
||||
*out = make([]WorkspaceNetworkPolicyIngressRule, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.Egress != nil {
|
||||
in, out := &in.Egress, &out.Egress
|
||||
*out = make([]WorkspaceNetworkPolicyEgressRule, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicySpec.
|
||||
|
||||
@@ -126,7 +126,6 @@ func (in *ServicePolicySpec) DeepCopyInto(out *ServicePolicySpec) {
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
in.Template.DeepCopyInto(&out.Template)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicePolicySpec.
|
||||
@@ -149,16 +148,6 @@ func (in *ServicePolicyStatus) DeepCopyInto(out *ServicePolicyStatus) {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.StartTime != nil {
|
||||
in, out := &in.StartTime, &out.StartTime
|
||||
*out = new(v1.Time)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.CompletionTime != nil {
|
||||
in, out := &in.CompletionTime, &out.CompletionTime
|
||||
*out = new(v1.Time)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicePolicyStatus.
|
||||
@@ -255,7 +244,6 @@ func (in *StrategySpec) DeepCopyInto(out *StrategySpec) {
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
in.Template.DeepCopyInto(&out.Template)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategySpec.
|
||||
@@ -278,16 +266,6 @@ func (in *StrategyStatus) DeepCopyInto(out *StrategyStatus) {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.StartTime != nil {
|
||||
in, out := &in.StartTime, &out.StartTime
|
||||
*out = new(v1.Time)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.CompletionTime != nil {
|
||||
in, out := &in.CompletionTime, &out.CompletionTime
|
||||
*out = new(v1.Time)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategyStatus.
|
||||
|
||||
26
pkg/controller/add_s2ibinary.go
Normal file
26
pkg/controller/add_s2ibinary.go
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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 controller
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/controller/s2ibinary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// AddToManagerFuncs is a list of functions to create controllers and add them to a manager.
|
||||
AddToManagerFuncs = append(AddToManagerFuncs, s2ibinary.Add)
|
||||
}
|
||||
169
pkg/controller/s2ibinary/s2ibinary_controller.go
Normal file
169
pkg/controller/s2ibinary/s2ibinary_controller.go
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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 s2ibinary
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||
)
|
||||
|
||||
var log = logf.Log.WithName("controller")
|
||||
|
||||
/**
|
||||
* USER ACTION REQUIRED: This is a scaffold file intended for the user to modify with their own Controller
|
||||
* business logic. Delete these comments after modifying this file.*
|
||||
*/
|
||||
|
||||
// Add creates a new S2iBinary Controller and adds it to the Manager with default RBAC. The Manager will set fields on the Controller
|
||||
// and Start it when the Manager is Started.
|
||||
func Add(mgr manager.Manager) error {
|
||||
return add(mgr, newReconciler(mgr))
|
||||
}
|
||||
|
||||
// newReconciler returns a new reconcile.Reconciler
|
||||
func newReconciler(mgr manager.Manager) reconcile.Reconciler {
|
||||
return &ReconcileS2iBinary{Client: mgr.GetClient(), scheme: mgr.GetScheme()}
|
||||
}
|
||||
|
||||
// add adds a new Controller to mgr with r as the reconcile.Reconciler
|
||||
func add(mgr manager.Manager, r reconcile.Reconciler) error {
|
||||
// Create a new controller
|
||||
c, err := controller.New("s2ibinary-controller", mgr, controller.Options{Reconciler: r})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Watch for changes to S2iBinary
|
||||
err = c.Watch(&source.Kind{Type: &devopsv1alpha1.S2iBinary{}}, &handler.EnqueueRequestForObject{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(user): Modify this to be the types you create
|
||||
// Uncomment watch a Deployment created by S2iBinary - change this for objects you create
|
||||
err = c.Watch(&source.Kind{Type: &appsv1.Deployment{}}, &handler.EnqueueRequestForOwner{
|
||||
IsController: true,
|
||||
OwnerType: &devopsv1alpha1.S2iBinary{},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ reconcile.Reconciler = &ReconcileS2iBinary{}
|
||||
|
||||
// ReconcileS2iBinary reconciles a S2iBinary object
|
||||
type ReconcileS2iBinary struct {
|
||||
client.Client
|
||||
scheme *runtime.Scheme
|
||||
}
|
||||
|
||||
// Reconcile reads that state of the cluster for a S2iBinary object and makes changes based on the state read
|
||||
// and what is in the S2iBinary.Spec
|
||||
// TODO(user): Modify this Reconcile function to implement your Controller logic. The scaffolding writes
|
||||
// a Deployment as an example
|
||||
// Automatically generate RBAC rules to allow the Controller to read and write Deployments
|
||||
// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
|
||||
// +kubebuilder:rbac:groups=apps,resources=deployments/status,verbs=get;update;patch
|
||||
// +kubebuilder:rbac:groups=devops.kubesphere.io,resources=s2ibinaries,verbs=get;list;watch;create;update;patch;delete
|
||||
// +kubebuilder:rbac:groups=devops.kubesphere.io,resources=s2ibinaries/status,verbs=get;update;patch
|
||||
func (r *ReconcileS2iBinary) Reconcile(request reconcile.Request) (reconcile.Result, error) {
|
||||
// Fetch the S2iBinary instance
|
||||
instance := &devopsv1alpha1.S2iBinary{}
|
||||
err := r.Get(context.TODO(), request.NamespacedName, instance)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
// Object not found, return. Created objects are automatically garbage collected.
|
||||
// For additional cleanup logic use finalizers.
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
// Error reading the object - requeue the request.
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
// TODO(user): Change this to be the object type created by your controller
|
||||
// Define the desired Deployment object
|
||||
deploy := &appsv1.Deployment{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: instance.Name + "-deployment",
|
||||
Namespace: instance.Namespace,
|
||||
},
|
||||
Spec: appsv1.DeploymentSpec{
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{"deployment": instance.Name + "-deployment"},
|
||||
},
|
||||
Template: corev1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"deployment": instance.Name + "-deployment"}},
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := controllerutil.SetControllerReference(instance, deploy, r.scheme); err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
// TODO(user): Change this for the object type created by your controller
|
||||
// Check if the Deployment already exists
|
||||
found := &appsv1.Deployment{}
|
||||
err = r.Get(context.TODO(), types.NamespacedName{Name: deploy.Name, Namespace: deploy.Namespace}, found)
|
||||
if err != nil && errors.IsNotFound(err) {
|
||||
log.Info("Creating Deployment", "namespace", deploy.Namespace, "name", deploy.Name)
|
||||
err = r.Create(context.TODO(), deploy)
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
} else if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
// TODO(user): Change this for the object type created by your controller
|
||||
// Update the found object and write the result back if there are any changes
|
||||
if !reflect.DeepEqual(deploy.Spec, found.Spec) {
|
||||
found.Spec = deploy.Spec
|
||||
log.Info("Updating Deployment", "namespace", deploy.Namespace, "name", deploy.Name)
|
||||
err = r.Update(context.TODO(), found)
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
}
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
75
pkg/controller/s2ibinary/s2ibinary_controller_suite_test.go
Normal file
75
pkg/controller/s2ibinary/s2ibinary_controller_suite_test.go
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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 s2ibinary
|
||||
|
||||
import (
|
||||
stdlog "log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/onsi/gomega"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
"kubesphere.io/kubesphere/pkg/apis"
|
||||
"sigs.k8s.io/controller-runtime/pkg/envtest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
)
|
||||
|
||||
var cfg *rest.Config
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
t := &envtest.Environment{
|
||||
CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crds")},
|
||||
}
|
||||
apis.AddToScheme(scheme.Scheme)
|
||||
|
||||
var err error
|
||||
if cfg, err = t.Start(); err != nil {
|
||||
stdlog.Fatal(err)
|
||||
}
|
||||
|
||||
code := m.Run()
|
||||
t.Stop()
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
// SetupTestReconcile returns a reconcile.Reconcile implementation that delegates to inner and
|
||||
// writes the request to requests after Reconcile is finished.
|
||||
func SetupTestReconcile(inner reconcile.Reconciler) (reconcile.Reconciler, chan reconcile.Request) {
|
||||
requests := make(chan reconcile.Request)
|
||||
fn := reconcile.Func(func(req reconcile.Request) (reconcile.Result, error) {
|
||||
result, err := inner.Reconcile(req)
|
||||
requests <- req
|
||||
return result, err
|
||||
})
|
||||
return fn, requests
|
||||
}
|
||||
|
||||
// StartTestManager adds recFn
|
||||
func StartTestManager(mgr manager.Manager, g *gomega.GomegaWithT) (chan struct{}, *sync.WaitGroup) {
|
||||
stop := make(chan struct{})
|
||||
wg := &sync.WaitGroup{}
|
||||
go func() {
|
||||
wg.Add(1)
|
||||
g.Expect(mgr.Start(stop)).NotTo(gomega.HaveOccurred())
|
||||
wg.Done()
|
||||
}()
|
||||
return stop, wg
|
||||
}
|
||||
87
pkg/controller/s2ibinary/s2ibinary_controller_test.go
Normal file
87
pkg/controller/s2ibinary/s2ibinary_controller_test.go
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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 s2ibinary
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/gomega"
|
||||
"golang.org/x/net/context"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
)
|
||||
|
||||
var c client.Client
|
||||
|
||||
var expectedRequest = reconcile.Request{NamespacedName: types.NamespacedName{Name: "foo", Namespace: "default"}}
|
||||
var depKey = types.NamespacedName{Name: "foo-deployment", Namespace: "default"}
|
||||
|
||||
const timeout = time.Second * 5
|
||||
|
||||
func TestReconcile(t *testing.T) {
|
||||
g := gomega.NewGomegaWithT(t)
|
||||
instance := &devopsv1alpha1.S2iBinary{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
|
||||
|
||||
// Setup the Manager and Controller. Wrap the Controller Reconcile function so it writes each request to a
|
||||
// channel when it is finished.
|
||||
mgr, err := manager.New(cfg, manager.Options{})
|
||||
g.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
c = mgr.GetClient()
|
||||
|
||||
recFn, requests := SetupTestReconcile(newReconciler(mgr))
|
||||
g.Expect(add(mgr, recFn)).NotTo(gomega.HaveOccurred())
|
||||
|
||||
stopMgr, mgrStopped := StartTestManager(mgr, g)
|
||||
|
||||
defer func() {
|
||||
close(stopMgr)
|
||||
mgrStopped.Wait()
|
||||
}()
|
||||
|
||||
// Create the S2iBinary object and expect the Reconcile and Deployment to be created
|
||||
err = c.Create(context.TODO(), instance)
|
||||
// The instance object may not be a valid object because it might be missing some required fields.
|
||||
// Please modify the instance object by adding required fields and then remove the following if statement.
|
||||
if apierrors.IsInvalid(err) {
|
||||
t.Logf("failed to create object, got an invalid object error: %v", err)
|
||||
return
|
||||
}
|
||||
g.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
defer c.Delete(context.TODO(), instance)
|
||||
g.Eventually(requests, timeout).Should(gomega.Receive(gomega.Equal(expectedRequest)))
|
||||
|
||||
deploy := &appsv1.Deployment{}
|
||||
g.Eventually(func() error { return c.Get(context.TODO(), depKey, deploy) }, timeout).
|
||||
Should(gomega.Succeed())
|
||||
|
||||
// Delete the Deployment and expect Reconcile to be called for Deployment deletion
|
||||
g.Expect(c.Delete(context.TODO(), deploy)).NotTo(gomega.HaveOccurred())
|
||||
g.Eventually(requests, timeout).Should(gomega.Receive(gomega.Equal(expectedRequest)))
|
||||
g.Eventually(func() error { return c.Get(context.TODO(), depKey, deploy) }, timeout).
|
||||
Should(gomega.Succeed())
|
||||
|
||||
// Manually delete Deployment since GC isn't enabled in the test control plane
|
||||
g.Expect(c.Delete(context.TODO(), deploy)).To(gomega.Succeed())
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user