mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-02-14 18:29:53 +00:00
Wish i could get this to be inline
This commit is contained in:
23
Makefile
23
Makefile
@@ -8,10 +8,18 @@ all: test manager
|
||||
test: generate fmt vet manifests
|
||||
go test ./pkg/... ./cmd/... -coverprofile cover.out
|
||||
|
||||
# Build manager binary
|
||||
.PHONY: manager
|
||||
manager: generate fmt vet
|
||||
go build -o bin/manager github.com/replicatedhq/troubleshoot/cmd/manager
|
||||
|
||||
.PHONY: troubleshoot
|
||||
troubleshoot: generate fmt vet
|
||||
go build -o bin/troubleshoot github.com/replicatedhq/troubleshoot/cmd/troubleshoot
|
||||
|
||||
.PHONY: preflight
|
||||
preflight: generate fmt vet
|
||||
go build -o bin/preflight github.com/replicatedhq/troubleshoot/cmd/preflight
|
||||
|
||||
# Run against the configured Kubernetes cluster in ~/.kube/config
|
||||
run: generate fmt vet
|
||||
go run ./cmd/manager/main.go
|
||||
@@ -26,22 +34,21 @@ deploy: manifests
|
||||
kustomize build config/default | kubectl apply -f -
|
||||
|
||||
# Generate manifests e.g. CRD, RBAC etc.
|
||||
manifests: controller-gen
|
||||
manifests:
|
||||
controller-gen paths=./pkg/apis/...
|
||||
|
||||
# Run go fmt against code
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
go fmt ./pkg/... ./cmd/...
|
||||
|
||||
# Run go vet against code
|
||||
.PHONY: vet
|
||||
vet:
|
||||
go vet ./pkg/... ./cmd/...
|
||||
|
||||
|
||||
.PHONY: generate
|
||||
generate: controller-gen client-gen
|
||||
controller-gen object:headerFile=./hack/boilerplate.go.txt paths=./api/...
|
||||
client-gen go run ../../vendor/k8s.io/code-generator/cmd/client-gen/main.go --output-package=github.com/replicatedhq/troubleshoot/pkg/client --clientset-name troubleshootclientset --input-base github.com/replicatedhq/troubleshoot/pkg/apis --input troubleshoot/v1beta1 -h ./hack/boilerplate.go.txt
|
||||
generate: controller-gen # client-gen
|
||||
controller-gen object:headerFile=./hack/boilerplate.go.txt paths=./pkg/apis/...
|
||||
# client-gen --output-package=github.com/replicatedhq/troubleshoot/pkg/client --clientset-name troubleshootclientset --input-base github.com/replicatedhq/troubleshoot/pkg/apis --input troubleshoot/v1beta1 -h ./hack/boilerplate.go.txt
|
||||
|
||||
# Build the docker image
|
||||
docker-build: test
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
|
||||
func main() {
|
||||
var metricsAddr string
|
||||
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
|
||||
flag.StringVar(&metricsAddr, "metrics-addr", ":8088", "The address the metric endpoint binds to.")
|
||||
flag.Parse()
|
||||
logf.SetLogger(logf.ZapLogger(false))
|
||||
log := logf.Log.WithName("entrypoint")
|
||||
|
||||
32
cmd/troubleshoot/cli/collect.go
Normal file
32
cmd/troubleshoot/cli/collect.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func Collect() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "collect",
|
||||
Short: "collect a support bundle from a cluster",
|
||||
Long: `...`,
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
viper.BindPFlag("collectors", cmd.Flags().Lookup("collectors"))
|
||||
viper.BindPFlag("namespace", cmd.Flags().Lookup("namespace"))
|
||||
viper.BindPFlag("kubecontext", cmd.Flags().Lookup("kubecontext"))
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().String("collectors", "", "name of the collectors to use")
|
||||
cmd.Flags().String("namespace", "", "namespace the collectors can be found in")
|
||||
|
||||
cmd.Flags().String("kubecontext", "", "the kubecontext to use when connecting")
|
||||
|
||||
viper.BindPFlags(cmd.Flags())
|
||||
|
||||
return cmd
|
||||
}
|
||||
39
cmd/troubleshoot/cli/root.go
Normal file
39
cmd/troubleshoot/cli/root.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func RootCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "troubleshoot",
|
||||
Short: "Generate and manage support bundles",
|
||||
Long: `A support bundle is an archive of files, output, metrics and state
|
||||
from a server that can be used to assist when troubleshooting a server.`,
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
cobra.OnInitialize(initConfig)
|
||||
|
||||
cmd.AddCommand(Collect())
|
||||
|
||||
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
||||
return cmd
|
||||
}
|
||||
|
||||
func InitAndExecute() {
|
||||
if err := RootCmd().Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func initConfig() {
|
||||
viper.SetEnvPrefix("TROUBLESHOT")
|
||||
viper.AutomaticEnv()
|
||||
}
|
||||
7
cmd/troubleshoot/main.go
Normal file
7
cmd/troubleshoot/main.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package main
|
||||
|
||||
import "github.com/replicatedhq/troubleshoot/cmd/troubleshoot/cli"
|
||||
|
||||
func main() {
|
||||
cli.InitAndExecute()
|
||||
}
|
||||
@@ -390,6 +390,595 @@ spec:
|
||||
type: string
|
||||
type: object
|
||||
spec:
|
||||
properties:
|
||||
collectors:
|
||||
items:
|
||||
properties:
|
||||
kubernetes.api-versions:
|
||||
properties:
|
||||
defer:
|
||||
type: boolean
|
||||
description:
|
||||
type: string
|
||||
include_empty:
|
||||
type: boolean
|
||||
meta:
|
||||
properties:
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
type: object
|
||||
output_dir:
|
||||
type: string
|
||||
scrub:
|
||||
properties:
|
||||
regex:
|
||||
type: string
|
||||
replace:
|
||||
type: string
|
||||
required:
|
||||
- regex
|
||||
- replace
|
||||
type: object
|
||||
timeout_seconds:
|
||||
type: integer
|
||||
type: object
|
||||
kubernetes.cluster-info:
|
||||
properties:
|
||||
defer:
|
||||
type: boolean
|
||||
description:
|
||||
type: string
|
||||
include_empty:
|
||||
type: boolean
|
||||
meta:
|
||||
properties:
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
type: object
|
||||
output_dir:
|
||||
type: string
|
||||
scrub:
|
||||
properties:
|
||||
regex:
|
||||
type: string
|
||||
replace:
|
||||
type: string
|
||||
required:
|
||||
- regex
|
||||
- replace
|
||||
type: object
|
||||
timeout_seconds:
|
||||
type: integer
|
||||
type: object
|
||||
kubernetes.container-cp:
|
||||
properties:
|
||||
container:
|
||||
type: string
|
||||
defer:
|
||||
type: boolean
|
||||
description:
|
||||
type: string
|
||||
include_empty:
|
||||
type: boolean
|
||||
meta:
|
||||
properties:
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
type: object
|
||||
namespace:
|
||||
type: string
|
||||
output_dir:
|
||||
type: string
|
||||
pod:
|
||||
type: string
|
||||
pod_list_options:
|
||||
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
|
||||
continue:
|
||||
description: "The continue option should be set when
|
||||
retrieving more results from the server. Since this
|
||||
value is server defined, clients may only use the
|
||||
continue value from a previous query result with identical
|
||||
query parameters (except for the value of continue)
|
||||
and the server may reject a continue value it does
|
||||
not recognize. If the specified continue value is
|
||||
no longer valid whether due to expiration (generally
|
||||
five to fifteen minutes) or a configuration change
|
||||
on the server, the server will respond with a 410
|
||||
ResourceExpired error together with a continue token.
|
||||
If the client needs a consistent list, it must restart
|
||||
their list without the continue field. Otherwise,
|
||||
the client may send another list request with the
|
||||
token received with the 410 error, the server will
|
||||
respond with a list starting from the next key, but
|
||||
from the latest snapshot, which is inconsistent from
|
||||
the previous list results - objects that are created,
|
||||
modified, or deleted after the first list request
|
||||
will be included in the response, as long as their
|
||||
keys are after the \"next key\". \n This field is
|
||||
not supported when watch is true. Clients may start
|
||||
a watch from the last resourceVersion value returned
|
||||
by the server and not miss any modifications."
|
||||
type: string
|
||||
fieldSelector:
|
||||
description: A selector to restrict the list of returned
|
||||
objects by their fields. Defaults to everything.
|
||||
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
|
||||
labelSelector:
|
||||
description: A selector to restrict the list of returned
|
||||
objects by their labels. Defaults to everything.
|
||||
type: string
|
||||
limit:
|
||||
description: "limit is a maximum number of responses
|
||||
to return for a list call. If more items exist, the
|
||||
server will set the `continue` field on the list metadata
|
||||
to a value that can be used with the same initial
|
||||
query to retrieve the next set of results. Setting
|
||||
a limit may return fewer than the requested amount
|
||||
of items (up to zero items) in the event all requested
|
||||
objects are filtered out and clients should only use
|
||||
the presence of the continue field to determine whether
|
||||
more results are available. Servers may choose not
|
||||
to support the limit argument and will return all
|
||||
of the available results. If limit is specified and
|
||||
the continue field is empty, clients may assume that
|
||||
no more results are available. This field is not supported
|
||||
if watch is true. \n The server guarantees that the
|
||||
objects returned when using continue will be identical
|
||||
to issuing a single list call without a limit - that
|
||||
is, no objects created, modified, or deleted after
|
||||
the first request is issued will be included in any
|
||||
subsequent continued requests. This is sometimes referred
|
||||
to as a consistent snapshot, and ensures that a client
|
||||
that is using limit to receive smaller chunks of a
|
||||
very large result can ensure they see all possible
|
||||
objects. If objects are updated during a chunked list
|
||||
the version of the object that was present at the
|
||||
time the first list result was calculated is returned."
|
||||
format: int64
|
||||
type: integer
|
||||
resourceVersion:
|
||||
description: 'When specified with a watch call, shows
|
||||
changes that occur after that particular version of
|
||||
a resource. Defaults to changes from the beginning
|
||||
of history. When specified for list: - if unset, then
|
||||
the result is returned from remote storage based on
|
||||
quorum-read flag; - if it''s 0, then we simply return
|
||||
what we currently have in cache, no guarantee; - if
|
||||
set to non zero, then the result is at least as fresh
|
||||
as given rv.'
|
||||
type: string
|
||||
timeoutSeconds:
|
||||
description: Timeout for the list/watch call. This limits
|
||||
the duration of the call, regardless of any activity
|
||||
or inactivity.
|
||||
format: int64
|
||||
type: integer
|
||||
watch:
|
||||
description: Watch for changes to the described resources
|
||||
and return them as a stream of add, update, and remove
|
||||
notifications. Specify resourceVersion.
|
||||
type: boolean
|
||||
type: object
|
||||
scrub:
|
||||
properties:
|
||||
regex:
|
||||
type: string
|
||||
replace:
|
||||
type: string
|
||||
required:
|
||||
- regex
|
||||
- replace
|
||||
type: object
|
||||
src_path:
|
||||
type: string
|
||||
timeout_seconds:
|
||||
type: integer
|
||||
type: object
|
||||
kubernetes.logs:
|
||||
properties:
|
||||
defer:
|
||||
type: boolean
|
||||
description:
|
||||
type: string
|
||||
include_empty:
|
||||
type: boolean
|
||||
list_options:
|
||||
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
|
||||
continue:
|
||||
description: "The continue option should be set when
|
||||
retrieving more results from the server. Since this
|
||||
value is server defined, clients may only use the
|
||||
continue value from a previous query result with identical
|
||||
query parameters (except for the value of continue)
|
||||
and the server may reject a continue value it does
|
||||
not recognize. If the specified continue value is
|
||||
no longer valid whether due to expiration (generally
|
||||
five to fifteen minutes) or a configuration change
|
||||
on the server, the server will respond with a 410
|
||||
ResourceExpired error together with a continue token.
|
||||
If the client needs a consistent list, it must restart
|
||||
their list without the continue field. Otherwise,
|
||||
the client may send another list request with the
|
||||
token received with the 410 error, the server will
|
||||
respond with a list starting from the next key, but
|
||||
from the latest snapshot, which is inconsistent from
|
||||
the previous list results - objects that are created,
|
||||
modified, or deleted after the first list request
|
||||
will be included in the response, as long as their
|
||||
keys are after the \"next key\". \n This field is
|
||||
not supported when watch is true. Clients may start
|
||||
a watch from the last resourceVersion value returned
|
||||
by the server and not miss any modifications."
|
||||
type: string
|
||||
fieldSelector:
|
||||
description: A selector to restrict the list of returned
|
||||
objects by their fields. Defaults to everything.
|
||||
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
|
||||
labelSelector:
|
||||
description: A selector to restrict the list of returned
|
||||
objects by their labels. Defaults to everything.
|
||||
type: string
|
||||
limit:
|
||||
description: "limit is a maximum number of responses
|
||||
to return for a list call. If more items exist, the
|
||||
server will set the `continue` field on the list metadata
|
||||
to a value that can be used with the same initial
|
||||
query to retrieve the next set of results. Setting
|
||||
a limit may return fewer than the requested amount
|
||||
of items (up to zero items) in the event all requested
|
||||
objects are filtered out and clients should only use
|
||||
the presence of the continue field to determine whether
|
||||
more results are available. Servers may choose not
|
||||
to support the limit argument and will return all
|
||||
of the available results. If limit is specified and
|
||||
the continue field is empty, clients may assume that
|
||||
no more results are available. This field is not supported
|
||||
if watch is true. \n The server guarantees that the
|
||||
objects returned when using continue will be identical
|
||||
to issuing a single list call without a limit - that
|
||||
is, no objects created, modified, or deleted after
|
||||
the first request is issued will be included in any
|
||||
subsequent continued requests. This is sometimes referred
|
||||
to as a consistent snapshot, and ensures that a client
|
||||
that is using limit to receive smaller chunks of a
|
||||
very large result can ensure they see all possible
|
||||
objects. If objects are updated during a chunked list
|
||||
the version of the object that was present at the
|
||||
time the first list result was calculated is returned."
|
||||
format: int64
|
||||
type: integer
|
||||
resourceVersion:
|
||||
description: 'When specified with a watch call, shows
|
||||
changes that occur after that particular version of
|
||||
a resource. Defaults to changes from the beginning
|
||||
of history. When specified for list: - if unset, then
|
||||
the result is returned from remote storage based on
|
||||
quorum-read flag; - if it''s 0, then we simply return
|
||||
what we currently have in cache, no guarantee; - if
|
||||
set to non zero, then the result is at least as fresh
|
||||
as given rv.'
|
||||
type: string
|
||||
timeoutSeconds:
|
||||
description: Timeout for the list/watch call. This limits
|
||||
the duration of the call, regardless of any activity
|
||||
or inactivity.
|
||||
format: int64
|
||||
type: integer
|
||||
watch:
|
||||
description: Watch for changes to the described resources
|
||||
and return them as a stream of add, update, and remove
|
||||
notifications. Specify resourceVersion.
|
||||
type: boolean
|
||||
type: object
|
||||
meta:
|
||||
properties:
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
type: object
|
||||
namespace:
|
||||
type: string
|
||||
output_dir:
|
||||
type: string
|
||||
pod:
|
||||
type: string
|
||||
pod_log_options:
|
||||
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
|
||||
container:
|
||||
description: The container for which to stream logs.
|
||||
Defaults to only container if there is one container
|
||||
in the pod.
|
||||
type: string
|
||||
follow:
|
||||
description: Follow the log stream of the pod. Defaults
|
||||
to false.
|
||||
type: boolean
|
||||
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
|
||||
limitBytes:
|
||||
description: If set, the number of bytes to read from
|
||||
the server before terminating the log output. This
|
||||
may not display a complete final line of logging,
|
||||
and may return slightly more or slightly less than
|
||||
the specified limit.
|
||||
format: int64
|
||||
type: integer
|
||||
previous:
|
||||
description: Return previous terminated container logs.
|
||||
Defaults to false.
|
||||
type: boolean
|
||||
sinceSeconds:
|
||||
description: A relative time in seconds before the current
|
||||
time from which to show logs. If this value precedes
|
||||
the time a pod was started, only logs since the pod
|
||||
start will be returned. If this value is in the future,
|
||||
no logs will be returned. Only one of sinceSeconds
|
||||
or sinceTime may be specified.
|
||||
format: int64
|
||||
type: integer
|
||||
sinceTime:
|
||||
description: An RFC3339 timestamp from which to show
|
||||
logs. If this value precedes the time a pod was started,
|
||||
only logs since the pod start will be returned. If
|
||||
this value is in the future, no logs will be returned.
|
||||
Only one of sinceSeconds or sinceTime may be specified.
|
||||
format: date-time
|
||||
type: string
|
||||
tailLines:
|
||||
description: If set, the number of lines from the end
|
||||
of the logs to show. If not specified, logs are shown
|
||||
from the creation of the container or sinceSeconds
|
||||
or sinceTime
|
||||
format: int64
|
||||
type: integer
|
||||
timestamps:
|
||||
description: If true, add an RFC3339 or RFC3339Nano
|
||||
timestamp at the beginning of every line of log output.
|
||||
Defaults to false.
|
||||
type: boolean
|
||||
type: object
|
||||
scrub:
|
||||
properties:
|
||||
regex:
|
||||
type: string
|
||||
replace:
|
||||
type: string
|
||||
required:
|
||||
- regex
|
||||
- replace
|
||||
type: object
|
||||
timeout_seconds:
|
||||
type: integer
|
||||
type: object
|
||||
kubernetes.resource-list:
|
||||
properties:
|
||||
defer:
|
||||
type: boolean
|
||||
description:
|
||||
type: string
|
||||
group_version:
|
||||
type: string
|
||||
include_empty:
|
||||
type: boolean
|
||||
kind:
|
||||
type: string
|
||||
meta:
|
||||
properties:
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
type: object
|
||||
namespace:
|
||||
type: string
|
||||
output_dir:
|
||||
type: string
|
||||
resource_list_options:
|
||||
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
|
||||
continue:
|
||||
description: "The continue option should be set when
|
||||
retrieving more results from the server. Since this
|
||||
value is server defined, clients may only use the
|
||||
continue value from a previous query result with identical
|
||||
query parameters (except for the value of continue)
|
||||
and the server may reject a continue value it does
|
||||
not recognize. If the specified continue value is
|
||||
no longer valid whether due to expiration (generally
|
||||
five to fifteen minutes) or a configuration change
|
||||
on the server, the server will respond with a 410
|
||||
ResourceExpired error together with a continue token.
|
||||
If the client needs a consistent list, it must restart
|
||||
their list without the continue field. Otherwise,
|
||||
the client may send another list request with the
|
||||
token received with the 410 error, the server will
|
||||
respond with a list starting from the next key, but
|
||||
from the latest snapshot, which is inconsistent from
|
||||
the previous list results - objects that are created,
|
||||
modified, or deleted after the first list request
|
||||
will be included in the response, as long as their
|
||||
keys are after the \"next key\". \n This field is
|
||||
not supported when watch is true. Clients may start
|
||||
a watch from the last resourceVersion value returned
|
||||
by the server and not miss any modifications."
|
||||
type: string
|
||||
fieldSelector:
|
||||
description: A selector to restrict the list of returned
|
||||
objects by their fields. Defaults to everything.
|
||||
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
|
||||
labelSelector:
|
||||
description: A selector to restrict the list of returned
|
||||
objects by their labels. Defaults to everything.
|
||||
type: string
|
||||
limit:
|
||||
description: "limit is a maximum number of responses
|
||||
to return for a list call. If more items exist, the
|
||||
server will set the `continue` field on the list metadata
|
||||
to a value that can be used with the same initial
|
||||
query to retrieve the next set of results. Setting
|
||||
a limit may return fewer than the requested amount
|
||||
of items (up to zero items) in the event all requested
|
||||
objects are filtered out and clients should only use
|
||||
the presence of the continue field to determine whether
|
||||
more results are available. Servers may choose not
|
||||
to support the limit argument and will return all
|
||||
of the available results. If limit is specified and
|
||||
the continue field is empty, clients may assume that
|
||||
no more results are available. This field is not supported
|
||||
if watch is true. \n The server guarantees that the
|
||||
objects returned when using continue will be identical
|
||||
to issuing a single list call without a limit - that
|
||||
is, no objects created, modified, or deleted after
|
||||
the first request is issued will be included in any
|
||||
subsequent continued requests. This is sometimes referred
|
||||
to as a consistent snapshot, and ensures that a client
|
||||
that is using limit to receive smaller chunks of a
|
||||
very large result can ensure they see all possible
|
||||
objects. If objects are updated during a chunked list
|
||||
the version of the object that was present at the
|
||||
time the first list result was calculated is returned."
|
||||
format: int64
|
||||
type: integer
|
||||
resourceVersion:
|
||||
description: 'When specified with a watch call, shows
|
||||
changes that occur after that particular version of
|
||||
a resource. Defaults to changes from the beginning
|
||||
of history. When specified for list: - if unset, then
|
||||
the result is returned from remote storage based on
|
||||
quorum-read flag; - if it''s 0, then we simply return
|
||||
what we currently have in cache, no guarantee; - if
|
||||
set to non zero, then the result is at least as fresh
|
||||
as given rv.'
|
||||
type: string
|
||||
timeoutSeconds:
|
||||
description: Timeout for the list/watch call. This limits
|
||||
the duration of the call, regardless of any activity
|
||||
or inactivity.
|
||||
format: int64
|
||||
type: integer
|
||||
watch:
|
||||
description: Watch for changes to the described resources
|
||||
and return them as a stream of add, update, and remove
|
||||
notifications. Specify resourceVersion.
|
||||
type: boolean
|
||||
type: object
|
||||
scrub:
|
||||
properties:
|
||||
regex:
|
||||
type: string
|
||||
replace:
|
||||
type: string
|
||||
required:
|
||||
- regex
|
||||
- replace
|
||||
type: object
|
||||
timeout_seconds:
|
||||
type: integer
|
||||
required:
|
||||
- kind
|
||||
type: object
|
||||
kubernetes.version:
|
||||
properties:
|
||||
defer:
|
||||
type: boolean
|
||||
description:
|
||||
type: string
|
||||
include_empty:
|
||||
type: boolean
|
||||
meta:
|
||||
properties:
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
type: object
|
||||
output_dir:
|
||||
type: string
|
||||
scrub:
|
||||
properties:
|
||||
regex:
|
||||
type: string
|
||||
replace:
|
||||
type: string
|
||||
required:
|
||||
- regex
|
||||
- replace
|
||||
type: object
|
||||
timeout_seconds:
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- collectors
|
||||
type: object
|
||||
status:
|
||||
type: object
|
||||
|
||||
@@ -13,7 +13,7 @@ spec:
|
||||
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.4.0
|
||||
args:
|
||||
- "--secure-listen-address=0.0.0.0:8443"
|
||||
- "--upstream=http://127.0.0.1:8080/"
|
||||
- "--upstream=http://127.0.0.1:8089/"
|
||||
- "--logtostderr=true"
|
||||
- "--v=10"
|
||||
ports:
|
||||
@@ -21,4 +21,4 @@ spec:
|
||||
name: https
|
||||
- name: manager
|
||||
args:
|
||||
- "--metrics-addr=127.0.0.1:8080"
|
||||
- "--metrics-addr=127.0.0.1:8088"
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
apiVersion: troubleshoot.replicated.com/v1beta1
|
||||
kind: Collector
|
||||
metadata:
|
||||
labels:
|
||||
controller-tools.k8s.io: "1.0"
|
||||
name: collector-sample
|
||||
spec:
|
||||
# Add fields here
|
||||
foo: bar
|
||||
collectors:
|
||||
- kubernetes.resource-list:
|
||||
output_dir: /kubernetes/resources/jobs
|
||||
kind: jobs
|
||||
namespace: ""
|
||||
- kubernetes.resource-list:
|
||||
output_dir: /kubernetes/resources/deployments
|
||||
kind: deployments
|
||||
namespace: ""
|
||||
- kubernetes.resource-list:
|
||||
output_dir: /kubernetes/resources/pods
|
||||
kind: pods
|
||||
namespace: ""
|
||||
- kubernetes.resource-list:
|
||||
output_dir: /kubernetes/resources/events
|
||||
kind: events
|
||||
namespace: ""
|
||||
|
||||
|
||||
10
go.sum
10
go.sum
@@ -47,6 +47,7 @@ github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6
|
||||
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
|
||||
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
@@ -129,6 +130,7 @@ github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCO
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
@@ -152,12 +154,14 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/markbates/inflect v1.0.4/go.mod h1:1fR9+pO2KHEO9ZRtto13gDwwZaAKstQzferVeWqbgNs=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@@ -183,6 +187,7 @@ github.com/pborman/uuid v0.0.0-20180906182336-adf5a7427709 h1:zNBQb37RGLmJybyMcs
|
||||
github.com/pborman/uuid v0.0.0-20180906182336-adf5a7427709/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
|
||||
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/petar/GoLLRB v0.0.0-20190514000832-33fb24c13b99/go.mod h1:HUpKUBZnpzkdx0kD/+Yfuft+uD3zHGtXF/XJB14TUr4=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||
@@ -229,16 +234,21 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
|
||||
72
pkg/apis/troubleshoot/v1beta1/collector_shared.go
Normal file
72
pkg/apis/troubleshoot/v1beta1/collector_shared.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type Meta struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
}
|
||||
|
||||
type Scrub struct {
|
||||
Regex string `json:"regex"`
|
||||
Replace string `json:"replace"`
|
||||
}
|
||||
|
||||
type SpecShared struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
OutputDir string `json:"output_dir,omitempty"`
|
||||
TimeoutSeconds int `json:"timeout_seconds,omitempty"`
|
||||
Scrub *Scrub `json:"scrub,omitempty"`
|
||||
IncludeEmpty bool `json:"include_empty,omitempty"`
|
||||
Meta *Meta `json:"meta,omitempty"`
|
||||
Defer bool `json:"defer,omitempty"`
|
||||
}
|
||||
|
||||
type KubernetesAPIVersionsOptions struct {
|
||||
SpecShared `json:",inline,omitempty"`
|
||||
}
|
||||
|
||||
type KubernetesClusterInfoOptions struct {
|
||||
SpecShared `json:",inline,omitempty"`
|
||||
}
|
||||
|
||||
type KubernetesVersionOptions struct {
|
||||
SpecShared `json:",inline,omitempty"`
|
||||
}
|
||||
|
||||
type KubernetesLogsOptions struct {
|
||||
SpecShared `json:",inline,omitempty"`
|
||||
Pod string `json:"pod,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
PodLogOptions *v1.PodLogOptions `json:"pod_log_options,omitempty"`
|
||||
ListOptions *metav1.ListOptions `json:"list_options,omitempty"`
|
||||
}
|
||||
|
||||
type KubernetesContainerCpOptions struct {
|
||||
SpecShared `json:",inline,omitempty"`
|
||||
Pod string `json:"pod,omitempty"`
|
||||
PodListOptions *metav1.ListOptions `json:"pod_list_options,omitempty"`
|
||||
Container string `json:"container,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
SrcPath string `json:"src_path,omitempty"`
|
||||
}
|
||||
|
||||
type KubernetesResourceListOptions struct {
|
||||
SpecShared `json:",inline,omitempty"`
|
||||
Kind string `json:"kind"`
|
||||
GroupVersion string `json:"group_version,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
ListOptions *metav1.ListOptions `json:"resource_list_options,omitempty"`
|
||||
}
|
||||
|
||||
type Collect struct {
|
||||
KubernetesAPIVersions *KubernetesAPIVersionsOptions `json:"kubernetes.api-versions,omitempty"`
|
||||
KubernetesClusterInfo *KubernetesClusterInfoOptions `json:"kubernetes.cluster-info,omitempty"`
|
||||
KubernetesContainerCp *KubernetesContainerCpOptions `json:"kubernetes.container-cp,omitempty"`
|
||||
KubernetesLogs *KubernetesLogsOptions `json:"kubernetes.logs,omitempty"`
|
||||
KubernetesResourceList *KubernetesResourceListOptions `json:"kubernetes.resource-list,omitempty"`
|
||||
KubernetesVersion *KubernetesVersionOptions `json:"kubernetes.version,omitempty"`
|
||||
}
|
||||
@@ -20,13 +20,9 @@ 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.
|
||||
|
||||
// CollectorSpec defines the desired state of Collector
|
||||
type CollectorSpec struct {
|
||||
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||
// Important: Run "make" to regenerate code after modifying this file
|
||||
Collectors []*Collect `json:"collectors"`
|
||||
}
|
||||
|
||||
// CollectorStatus defines the observed state of Collector
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
@@ -186,12 +188,57 @@ func (in *AnalyzerStatus) DeepCopy() *AnalyzerStatus {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Collect) DeepCopyInto(out *Collect) {
|
||||
*out = *in
|
||||
if in.KubernetesAPIVersions != nil {
|
||||
in, out := &in.KubernetesAPIVersions, &out.KubernetesAPIVersions
|
||||
*out = new(KubernetesAPIVersionsOptions)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.KubernetesClusterInfo != nil {
|
||||
in, out := &in.KubernetesClusterInfo, &out.KubernetesClusterInfo
|
||||
*out = new(KubernetesClusterInfoOptions)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.KubernetesContainerCp != nil {
|
||||
in, out := &in.KubernetesContainerCp, &out.KubernetesContainerCp
|
||||
*out = new(KubernetesContainerCpOptions)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.KubernetesLogs != nil {
|
||||
in, out := &in.KubernetesLogs, &out.KubernetesLogs
|
||||
*out = new(KubernetesLogsOptions)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.KubernetesResourceList != nil {
|
||||
in, out := &in.KubernetesResourceList, &out.KubernetesResourceList
|
||||
*out = new(KubernetesResourceListOptions)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.KubernetesVersion != nil {
|
||||
in, out := &in.KubernetesVersion, &out.KubernetesVersion
|
||||
*out = new(KubernetesVersionOptions)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Collect.
|
||||
func (in *Collect) DeepCopy() *Collect {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Collect)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Collector) DeepCopyInto(out *Collector) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
out.Status = in.Status
|
||||
}
|
||||
|
||||
@@ -337,6 +384,17 @@ func (in *CollectorList) DeepCopyObject() runtime.Object {
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CollectorSpec) DeepCopyInto(out *CollectorSpec) {
|
||||
*out = *in
|
||||
if in.Collectors != nil {
|
||||
in, out := &in.Collectors, &out.Collectors
|
||||
*out = make([]*Collect, len(*in))
|
||||
for i := range *in {
|
||||
if (*in)[i] != nil {
|
||||
in, out := &(*in)[i], &(*out)[i]
|
||||
*out = new(Collect)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CollectorSpec.
|
||||
@@ -364,6 +422,144 @@ func (in *CollectorStatus) DeepCopy() *CollectorStatus {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubernetesAPIVersionsOptions) DeepCopyInto(out *KubernetesAPIVersionsOptions) {
|
||||
*out = *in
|
||||
in.SpecShared.DeepCopyInto(&out.SpecShared)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesAPIVersionsOptions.
|
||||
func (in *KubernetesAPIVersionsOptions) DeepCopy() *KubernetesAPIVersionsOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KubernetesAPIVersionsOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubernetesClusterInfoOptions) DeepCopyInto(out *KubernetesClusterInfoOptions) {
|
||||
*out = *in
|
||||
in.SpecShared.DeepCopyInto(&out.SpecShared)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesClusterInfoOptions.
|
||||
func (in *KubernetesClusterInfoOptions) DeepCopy() *KubernetesClusterInfoOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KubernetesClusterInfoOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubernetesContainerCpOptions) DeepCopyInto(out *KubernetesContainerCpOptions) {
|
||||
*out = *in
|
||||
in.SpecShared.DeepCopyInto(&out.SpecShared)
|
||||
if in.PodListOptions != nil {
|
||||
in, out := &in.PodListOptions, &out.PodListOptions
|
||||
*out = new(metav1.ListOptions)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesContainerCpOptions.
|
||||
func (in *KubernetesContainerCpOptions) DeepCopy() *KubernetesContainerCpOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KubernetesContainerCpOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubernetesLogsOptions) DeepCopyInto(out *KubernetesLogsOptions) {
|
||||
*out = *in
|
||||
in.SpecShared.DeepCopyInto(&out.SpecShared)
|
||||
if in.PodLogOptions != nil {
|
||||
in, out := &in.PodLogOptions, &out.PodLogOptions
|
||||
*out = new(v1.PodLogOptions)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ListOptions != nil {
|
||||
in, out := &in.ListOptions, &out.ListOptions
|
||||
*out = new(metav1.ListOptions)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesLogsOptions.
|
||||
func (in *KubernetesLogsOptions) DeepCopy() *KubernetesLogsOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KubernetesLogsOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubernetesResourceListOptions) DeepCopyInto(out *KubernetesResourceListOptions) {
|
||||
*out = *in
|
||||
in.SpecShared.DeepCopyInto(&out.SpecShared)
|
||||
if in.ListOptions != nil {
|
||||
in, out := &in.ListOptions, &out.ListOptions
|
||||
*out = new(metav1.ListOptions)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesResourceListOptions.
|
||||
func (in *KubernetesResourceListOptions) DeepCopy() *KubernetesResourceListOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KubernetesResourceListOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubernetesVersionOptions) DeepCopyInto(out *KubernetesVersionOptions) {
|
||||
*out = *in
|
||||
in.SpecShared.DeepCopyInto(&out.SpecShared)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesVersionOptions.
|
||||
func (in *KubernetesVersionOptions) DeepCopy() *KubernetesVersionOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KubernetesVersionOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Meta) DeepCopyInto(out *Meta) {
|
||||
*out = *in
|
||||
if in.Labels != nil {
|
||||
in, out := &in.Labels, &out.Labels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Meta.
|
||||
func (in *Meta) DeepCopy() *Meta {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Meta)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Preflight) DeepCopyInto(out *Preflight) {
|
||||
*out = *in
|
||||
@@ -541,3 +737,43 @@ func (in *PreflightStatus) DeepCopy() *PreflightStatus {
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Scrub) DeepCopyInto(out *Scrub) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Scrub.
|
||||
func (in *Scrub) DeepCopy() *Scrub {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Scrub)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *SpecShared) DeepCopyInto(out *SpecShared) {
|
||||
*out = *in
|
||||
if in.Scrub != nil {
|
||||
in, out := &in.Scrub, &out.Scrub
|
||||
*out = new(Scrub)
|
||||
**out = **in
|
||||
}
|
||||
if in.Meta != nil {
|
||||
in, out := &in.Meta, &out.Meta
|
||||
*out = new(Meta)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SpecShared.
|
||||
func (in *SpecShared) DeepCopy() *SpecShared {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(SpecShared)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -18,18 +18,13 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
|
||||
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"
|
||||
"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"
|
||||
@@ -92,8 +87,6 @@ type ReconcileCollector struct {
|
||||
|
||||
// Reconcile reads that state of the cluster for a Collector object and makes changes based on the state read
|
||||
// and what is in the Collector.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
|
||||
@@ -113,55 +106,5 @@ func (r *ReconcileCollector) Reconcile(request reconcile.Request) (reconcile.Res
|
||||
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)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -18,71 +18,8 @@ package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/gomega"
|
||||
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
|
||||
"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"
|
||||
"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 := &troubleshootv1beta1.Collector{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 Collector 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.Eventually(func() error { return c.Delete(context.TODO(), deploy) }, timeout).
|
||||
Should(gomega.MatchError("deployments.apps \"foo-deployment\" not found"))
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user