diff --git a/apis/v1alpha1/ack-generate-metadata.yaml b/apis/v1alpha1/ack-generate-metadata.yaml index 075a0ac..065efb2 100755 --- a/apis/v1alpha1/ack-generate-metadata.yaml +++ b/apis/v1alpha1/ack-generate-metadata.yaml @@ -1,9 +1,9 @@ ack_generate_info: - build_date: "2023-05-15T22:59:25Z" - build_hash: 8f3ba427974fd6e769926778d54834eaee3b81a3 - go_version: go1.19 - version: v0.26.1 -api_directory_checksum: 4f7fb701a99ba2779fc1f32a9038e16d190b07ff + build_date: "2023-12-22T00:44:45Z" + build_hash: 1f16813c807af6889060b4ce7ded2a69dc027d8c + go_version: go1.21.5 + version: v0.28.0 +api_directory_checksum: 6436937f9268efc8ffe6e7994e4f5290ccbcc3dc api_version: v1alpha1 aws_sdk_go_version: v1.44.93 generator_config_info: diff --git a/cmd/controller/main.go b/cmd/controller/main.go index 2abb93c..1013b52 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -87,13 +87,14 @@ func main() { } mgr, err := ctrlrt.NewManager(ctrlrt.GetConfigOrDie(), ctrlrt.Options{ - Scheme: scheme, - Port: port, - Host: host, - MetricsBindAddress: ackCfg.MetricsAddr, - LeaderElection: ackCfg.EnableLeaderElection, - LeaderElectionID: awsServiceAPIGroup, - Namespace: ackCfg.WatchNamespace, + Scheme: scheme, + Port: port, + Host: host, + MetricsBindAddress: ackCfg.MetricsAddr, + LeaderElection: ackCfg.EnableLeaderElection, + LeaderElectionID: "ack-" + awsServiceAPIGroup, + Namespace: ackCfg.WatchNamespace, + LeaderElectionNamespace: ackCfg.LeaderElectionNamespace, }) if err != nil { setupLog.Error( diff --git a/config/controller/deployment.yaml b/config/controller/deployment.yaml index 72c2513..a813c96 100644 --- a/config/controller/deployment.yaml +++ b/config/controller/deployment.yaml @@ -29,14 +29,16 @@ spec: - "$(AWS_REGION)" - --aws-endpoint-url - "$(AWS_ENDPOINT_URL)" - - --enable-development-logging - - "$(ACK_ENABLE_DEVELOPMENT_LOGGING)" + - --enable-development-logging=$(ACK_ENABLE_DEVELOPMENT_LOGGING) - --log-level - "$(ACK_LOG_LEVEL)" - --resource-tags - "$(ACK_RESOURCE_TAGS)" - --watch-namespace - "$(ACK_WATCH_NAMESPACE)" + - --enable-leader-election=$(ENABLE_LEADER_ELECTION) + - --leader-election-namespace + - "$(LEADER_ELECTION_NAMESPACE)" image: controller:latest name: controller ports: @@ -66,6 +68,10 @@ spec: value: "info" - name: ACK_RESOURCE_TAGS value: "services.k8s.aws/controller-version=%CONTROLLER_SERVICE%-%CONTROLLER_VERSION%,services.k8s.aws/namespace=%K8S_NAMESPACE%" + - name: ENABLE_LEADER_ELECTION + value: "false" + - name: LEADER_ELECTION_NAMESPACE + value: "ack-system" securityContext: allowPrivilegeEscalation: false privileged: false @@ -79,5 +85,6 @@ spec: terminationGracePeriodSeconds: 10 serviceAccountName: ack-mq-controller hostIPC: false - hostNetwork: false hostPID: false + hostNetwork: false + dnsPolicy: ClusterFirst diff --git a/config/controller/kustomization.yaml b/config/controller/kustomization.yaml index 1edc9d0..38e58ae 100644 --- a/config/controller/kustomization.yaml +++ b/config/controller/kustomization.yaml @@ -6,4 +6,4 @@ kind: Kustomization images: - name: controller newName: public.ecr.aws/aws-controllers-k8s/mq-controller - newTag: 0.0.28 + newTag: 0.0.29 diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml index eb7df60..d9acdee 100644 --- a/config/rbac/kustomization.yaml +++ b/config/rbac/kustomization.yaml @@ -4,4 +4,5 @@ resources: - role-reader.yaml - role-writer.yaml - service-account.yaml - +- leader-election-role.yaml +- leader-election-role-binding.yaml diff --git a/config/rbac/leader-election-role-binding.yaml b/config/rbac/leader-election-role-binding.yaml new file mode 100644 index 0000000..4ef4e29 --- /dev/null +++ b/config/rbac/leader-election-role-binding.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + namespace: ack-system + name: mq-leader-election-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: mq-leader-election-role +subjects: +- kind: ServiceAccount + name: ack-mq-controller + namespace: ack-system diff --git a/config/rbac/leader-election-role.yaml b/config/rbac/leader-election-role.yaml new file mode 100644 index 0000000..4537452 --- /dev/null +++ b/config/rbac/leader-election-role.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: mq-leader-election-role + namespace: ack-system +rules: +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/go.mod b/go.mod index 208afac..6c0561f 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,13 @@ go 1.19 require ( github.com/aws-controllers-k8s/ec2-controller v0.0.21 - github.com/aws-controllers-k8s/runtime v0.26.0 - github.com/aws/aws-sdk-go v1.44.93 + github.com/aws-controllers-k8s/runtime v0.28.0 + github.com/aws/aws-sdk-go v1.49.0 github.com/go-logr/logr v1.2.3 github.com/spf13/pflag v1.0.5 - k8s.io/api v0.26.1 - k8s.io/apimachinery v0.26.1 - k8s.io/client-go v0.26.1 + k8s.io/api v0.26.8 + k8s.io/apimachinery v0.26.8 + k8s.io/client-go v0.26.8 sigs.k8s.io/controller-runtime v0.14.5 ) @@ -32,7 +32,7 @@ require ( github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.1.0 // indirect - github.com/google/uuid v1.1.2 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/itchyny/gojq v0.12.6 // indirect github.com/itchyny/timefmt-go v0.1.3 // indirect @@ -55,11 +55,11 @@ require ( go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect - golang.org/x/net v0.7.0 // indirect + golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/term v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index e303afa..79d9ee9 100644 --- a/go.sum +++ b/go.sum @@ -40,10 +40,10 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/aws-controllers-k8s/ec2-controller v0.0.21 h1:5O7/9aED2Tl9OT0TL2rWrc1Ix5V1UxYEgDKAhvFhPJQ= github.com/aws-controllers-k8s/ec2-controller v0.0.21/go.mod h1:OMsmJeJ3iQZ1sJgs3hqnjBRnJ3hmTzJUO38W5rxnB5M= -github.com/aws-controllers-k8s/runtime v0.26.0 h1:XKqygFzHSBtM74Ov9IroZbyCVeYei9Eskp4aKbJ2SFw= -github.com/aws-controllers-k8s/runtime v0.26.0/go.mod h1:jizDzKikL09cueIuA9ZxoZ+4pfn5U7oKW5s/ZAqOA6E= -github.com/aws/aws-sdk-go v1.44.93 h1:hAgd9fuaptBatSft27/5eBMdcA8+cIMqo96/tZ6rKl8= -github.com/aws/aws-sdk-go v1.44.93/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/aws-controllers-k8s/runtime v0.28.0 h1:QhtZDwF4TId5rBW924FMMKWFb0PGTtclVj+Cyj3bRaI= +github.com/aws-controllers-k8s/runtime v0.28.0/go.mod h1:OYbm782YcAQDN1M5k3lttI16FcLoiRqrIQL0DvU3+Lg= +github.com/aws/aws-sdk-go v1.49.0 h1:g9BkW1fo9GqKfwg2+zCD+TW/D36Ux+vtfJ8guF4AYmY= +github.com/aws/aws-sdk-go v1.49.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -165,8 +165,8 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -371,8 +371,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -433,12 +433,12 @@ golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -446,8 +446,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -611,14 +611,14 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= -k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= +k8s.io/api v0.26.8 h1:k2OtFmQPWfDUyAuYAwQPftVygF/vz4BMGSKnd15iddM= +k8s.io/api v0.26.8/go.mod h1:QaflR7cmG3V9lIz0VLBM+ylndNN897OAUAoJDcgwiQw= k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= -k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= -k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= -k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= -k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= +k8s.io/apimachinery v0.26.8 h1:SzpGtRX3/j/Ylg8Eg65Iobpxi9Jz4vOvI0qcBZyPVrM= +k8s.io/apimachinery v0.26.8/go.mod h1:qYzLkrQ9lhrZRh0jNKo2cfvf/R1/kQONnSiyB7NUJU0= +k8s.io/client-go v0.26.8 h1:pPuTYaVtLlg/7n6rqs3MsKLi4XgNaJ3rTMyS37Y5CKU= +k8s.io/client-go v0.26.8/go.mod h1:1sBQqKmdy9rWZYQnoedpc0gnRXG7kU3HrKZvBe2QbGM= k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= diff --git a/helm/Chart.yaml b/helm/Chart.yaml index e082a40..0a853f3 100644 --- a/helm/Chart.yaml +++ b/helm/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v1 name: mq-chart description: A Helm chart for the ACK service controller for Amazon MQ (MQ) -version: 0.0.28 -appVersion: 0.0.28 +version: 0.0.29 +appVersion: 0.0.29 home: https://github.com/aws-controllers-k8s/mq-controller icon: https://raw.githubusercontent.com/aws/eks-charts/master/docs/logo/aws.png sources: diff --git a/helm/templates/NOTES.txt b/helm/templates/NOTES.txt index f9132d6..7b8e0c9 100644 --- a/helm/templates/NOTES.txt +++ b/helm/templates/NOTES.txt @@ -1,5 +1,5 @@ {{ .Chart.Name }} has been installed. -This chart deploys "public.ecr.aws/aws-controllers-k8s/mq-controller:0.0.28". +This chart deploys "public.ecr.aws/aws-controllers-k8s/mq-controller:0.0.29". Check its status by running: kubectl --namespace {{ .Release.Namespace }} get pods -l "app.kubernetes.io/instance={{ .Release.Name }}" diff --git a/helm/templates/deployment.yaml b/helm/templates/deployment.yaml index 7504a61..cea38ec 100644 --- a/helm/templates/deployment.yaml +++ b/helm/templates/deployment.yaml @@ -11,17 +11,19 @@ metadata: k8s-app: {{ include "app.name" . }} helm.sh/chart: {{ include "chart.name-version" . }} spec: - replicas: 1 + replicas: {{ .Values.deployment.replicas }} selector: matchLabels: app.kubernetes.io/name: {{ include "app.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} template: metadata: +{{- if .Values.deployment.annotations }} annotations: {{- range $key, $value := .Values.deployment.annotations }} {{ $key }}: {{ $value | quote }} {{- end }} +{{- end }} labels: app.kubernetes.io/name: {{ include "app.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} @@ -46,8 +48,9 @@ spec: - "$(AWS_REGION)" - --aws-endpoint-url - "$(AWS_ENDPOINT_URL)" +{{- if .Values.log.enable_development_logging }} - --enable-development-logging - - "$(ACK_ENABLE_DEVELOPMENT_LOGGING)" +{{- end }} - --log-level - "$(ACK_LOG_LEVEL)" - --resource-tags @@ -56,6 +59,11 @@ spec: - "$(ACK_WATCH_NAMESPACE)" - --deletion-policy - "$(DELETION_POLICY)" +{{- if .Values.leaderElection.enabled }} + - --enable-leader-election + - --leader-election-namespace + - "$(LEADER_ELECTION_NAMESPACE)" +{{- end }} {{- if gt .Values.reconcile.defaultResyncPeriod 0.0 }} - --reconcile-default-resync-seconds - "$(RECONCILE_DEFAULT_RESYNC_SECONDS)" @@ -85,8 +93,8 @@ spec: value: {{ include "watch-namespace" . }} - name: DELETION_POLICY value: {{ .Values.deletionPolicy }} - - name: ACK_ENABLE_DEVELOPMENT_LOGGING - value: {{ .Values.log.enable_development_logging | quote }} + - name: LEADER_ELECTION_NAMESPACE + value: {{ .Values.leaderElection.namespace | quote }} - name: ACK_LOG_LEVEL value: {{ .Values.log.level | quote }} - name: ACK_RESOURCE_TAGS @@ -104,11 +112,19 @@ spec: value: {{ include "aws.credentials.path" . }} - name: AWS_PROFILE value: {{ .Values.aws.credentials.profile }} + {{- end }} + {{- if .Values.deployment.extraEnvVars -}} + {{ toYaml .Values.deployment.extraEnvVars | nindent 8 }} + {{- end }} volumeMounts: + {{- if .Values.aws.credentials.secretName }} - name: {{ .Values.aws.credentials.secretName }} mountPath: {{ include "aws.credentials.secret_mount_path" . }} readOnly: true {{- end }} + {{- if .Values.deployment.extraVolumeMounts -}} + {{ toYaml .Values.deployment.extraVolumeMounts | nindent 10 }} + {{- end }} securityContext: allowPrivilegeEscalation: false privileged: false @@ -131,11 +147,15 @@ spec: priorityClassName: {{ .Values.deployment.priorityClassName }} {{ end -}} hostIPC: false - hostNetwork: false hostPID: false - {{ if .Values.aws.credentials.secretName -}} + hostNetwork: {{ .Values.deployment.hostNetwork }} + dnsPolicy: {{ .Values.deployment.dnsPolicy }} volumes: + {{- if .Values.aws.credentials.secretName }} - name: {{ .Values.aws.credentials.secretName }} secret: secretName: {{ .Values.aws.credentials.secretName }} - {{ end -}} + {{- end }} +{{- if .Values.deployment.extraVolumes }} +{{ toYaml .Values.deployment.extraVolumes | indent 8}} +{{- end }} diff --git a/helm/templates/leader-election-role-binding.yaml b/helm/templates/leader-election-role-binding.yaml new file mode 100644 index 0000000..50c38b7 --- /dev/null +++ b/helm/templates/leader-election-role-binding.yaml @@ -0,0 +1,18 @@ +{{ if .Values.leaderElection.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: mq-leader-election-rolebinding +{{ if .Values.leaderElection.namespace }} + namespace: {{ .Values.leaderElection.namespace }} +{{ else }} + namespace: {{ .Release.Namespace }} +{{ end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: mq-leader-election-role +subjects: +- kind: ServiceAccount + name: {{ include "service-account.name" . }} + namespace: {{ .Release.Namespace }}{{- end }} diff --git a/helm/templates/leader-election-role.yaml b/helm/templates/leader-election-role.yaml new file mode 100644 index 0000000..664af49 --- /dev/null +++ b/helm/templates/leader-election-role.yaml @@ -0,0 +1,30 @@ +{{ if .Values.leaderElection.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: mq-leader-election-role +{{ if .Values.leaderElection.namespace }} + namespace: {{ .Values.leaderElection.namespace }} +{{ else }} + namespace: {{ .Release.Namespace }} +{{ end }} +rules: +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch{{- end }} diff --git a/helm/values.schema.json b/helm/values.schema.json index 79fd18c..ac28b68 100644 --- a/helm/values.schema.json +++ b/helm/values.schema.json @@ -47,6 +47,9 @@ "minimum": 1, "maximum": 65535 }, + "replicas": { + "type": "integer" + }, "nodeSelector": { "type": "object" }, @@ -58,6 +61,15 @@ }, "priorityClassName": { "type": "string" + }, + "extraVolumeMounts": { + "type": "array" + }, + "extraVolumes": { + "type": "array" + }, + "extraEnvVars": { + "type": "array" } }, "required": [ @@ -222,6 +234,18 @@ }, "type": "object" }, + "leaderElection": { + "description": "Parameter to configure the controller's leader election system.", + "properties": { + "enabled": { + "type": "boolean" + }, + "namespace": { + "type": "string" + } + }, + "type": "object" + }, "serviceAccount": { "description": "ServiceAccount settings", "properties": { diff --git a/helm/values.yaml b/helm/values.yaml index fba278b..4078258 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -4,7 +4,7 @@ image: repository: public.ecr.aws/aws-controllers-k8s/mq-controller - tag: 0.0.28 + tag: 0.0.29 pullPolicy: IfNotPresent pullSecrets: [] @@ -15,6 +15,10 @@ deployment: annotations: {} labels: {} containerPort: 8080 + # Number of Deployment replicas + # This determines how many instances of the controller will be running. It's recommended + # to enable leader election if you need to increase the number of replicas > 1 + replicas: 1 # Which nodeSelector to set? # See: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector nodeSelector: @@ -28,11 +32,40 @@ deployment: # Which priorityClassName to set? # See: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#pod-priority priorityClassName: "" + # Specifies the hostname of the Pod. + # If not specified, the pod's hostname will be set to a system-defined value. + hostNetwork: false + # Set DNS policy for the pod. + # Defaults to "ClusterFirst". + # Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. + # To have DNS options set along with hostNetwork, you have to specify DNS policy + # explicitly to 'ClusterFirstWithHostNet'. + dnsPolicy: ClusterFirst + extraVolumes: [] + extraVolumeMounts: [] + + # Additional server container environment variables + # + # You specify this manually like you would a raw deployment manifest. + # This means you can bind in environment variables from secrets. + # + # e.g. static environment variable: + # - name: DEMO_GREETING + # value: "Hello from the environment" + # + # e.g. secret environment variable: + # - name: USERNAME + # valueFrom: + # secretKeyRef: + # name: mysecret + # key: username + extraEnvVars: [] + # If "installScope: cluster" then these labels will be applied to ClusterRole role: labels: {} - + metrics: service: # Set to true to automatically create a Kubernetes Service resource for the @@ -60,7 +93,7 @@ aws: # Secret stringData key that contains the credentials secretKey: "credentials" # Profile used for AWS credentials - profile: "default" + profile: "default" # log level for the controller log: @@ -90,7 +123,7 @@ deletionPolicy: delete # controller reconciliation configurations reconcile: # The default duration, in seconds, to wait before resyncing desired state of custom resources. - defaultResyncPeriod: 0 + defaultResyncPeriod: 36000 # 10 Hours # An object representing the reconcile resync configuration for each specific resource. resourceResyncPeriods: {} @@ -101,3 +134,15 @@ serviceAccount: name: ack-mq-controller annotations: {} # eks.amazonaws.com/role-arn: arn:aws:iam::AWS_ACCOUNT_ID:role/IAM_ROLE_NAME + +# Configuration of the leader election. Required for running multiple instances of the +# controller within the same cluster. +# See https://kubernetes.io/docs/concepts/architecture/leases/#leader-election +leaderElection: + # Enable Controller Leader Election. Set this to true to enable leader election + # for this controller. + enabled: false + # Leader election can be scoped to a specific namespace. By default, the controller + # will attempt to use the namespace of the service account mounted to the Controller + # pod. + namespace: "" diff --git a/pkg/resource/broker/delta.go b/pkg/resource/broker/delta.go index d135c09..f1399dd 100644 --- a/pkg/resource/broker/delta.go +++ b/pkg/resource/broker/delta.go @@ -131,8 +131,12 @@ func newResourceDelta( if ackcompare.HasNilDifference(a.ko.Spec.LDAPServerMetadata, b.ko.Spec.LDAPServerMetadata) { delta.Add("Spec.LDAPServerMetadata", a.ko.Spec.LDAPServerMetadata, b.ko.Spec.LDAPServerMetadata) } else if a.ko.Spec.LDAPServerMetadata != nil && b.ko.Spec.LDAPServerMetadata != nil { - if !ackcompare.SliceStringPEqual(a.ko.Spec.LDAPServerMetadata.Hosts, b.ko.Spec.LDAPServerMetadata.Hosts) { + if len(a.ko.Spec.LDAPServerMetadata.Hosts) != len(b.ko.Spec.LDAPServerMetadata.Hosts) { delta.Add("Spec.LDAPServerMetadata.Hosts", a.ko.Spec.LDAPServerMetadata.Hosts, b.ko.Spec.LDAPServerMetadata.Hosts) + } else if len(a.ko.Spec.LDAPServerMetadata.Hosts) > 0 { + if !ackcompare.SliceStringPEqual(a.ko.Spec.LDAPServerMetadata.Hosts, b.ko.Spec.LDAPServerMetadata.Hosts) { + delta.Add("Spec.LDAPServerMetadata.Hosts", a.ko.Spec.LDAPServerMetadata.Hosts, b.ko.Spec.LDAPServerMetadata.Hosts) + } } if ackcompare.HasNilDifference(a.ko.Spec.LDAPServerMetadata.RoleBase, b.ko.Spec.LDAPServerMetadata.RoleBase) { delta.Add("Spec.LDAPServerMetadata.RoleBase", a.ko.Spec.LDAPServerMetadata.RoleBase, b.ko.Spec.LDAPServerMetadata.RoleBase) @@ -265,8 +269,12 @@ func newResourceDelta( if !reflect.DeepEqual(a.ko.Spec.SecurityGroupRefs, b.ko.Spec.SecurityGroupRefs) { delta.Add("Spec.SecurityGroupRefs", a.ko.Spec.SecurityGroupRefs, b.ko.Spec.SecurityGroupRefs) } - if !ackcompare.SliceStringPEqual(a.ko.Spec.SecurityGroups, b.ko.Spec.SecurityGroups) { + if len(a.ko.Spec.SecurityGroups) != len(b.ko.Spec.SecurityGroups) { delta.Add("Spec.SecurityGroups", a.ko.Spec.SecurityGroups, b.ko.Spec.SecurityGroups) + } else if len(a.ko.Spec.SecurityGroups) > 0 { + if !ackcompare.SliceStringPEqual(a.ko.Spec.SecurityGroups, b.ko.Spec.SecurityGroups) { + delta.Add("Spec.SecurityGroups", a.ko.Spec.SecurityGroups, b.ko.Spec.SecurityGroups) + } } if ackcompare.HasNilDifference(a.ko.Spec.StorageType, b.ko.Spec.StorageType) { delta.Add("Spec.StorageType", a.ko.Spec.StorageType, b.ko.Spec.StorageType) @@ -275,8 +283,12 @@ func newResourceDelta( delta.Add("Spec.StorageType", a.ko.Spec.StorageType, b.ko.Spec.StorageType) } } - if !ackcompare.SliceStringPEqual(a.ko.Spec.SubnetIDs, b.ko.Spec.SubnetIDs) { + if len(a.ko.Spec.SubnetIDs) != len(b.ko.Spec.SubnetIDs) { delta.Add("Spec.SubnetIDs", a.ko.Spec.SubnetIDs, b.ko.Spec.SubnetIDs) + } else if len(a.ko.Spec.SubnetIDs) > 0 { + if !ackcompare.SliceStringPEqual(a.ko.Spec.SubnetIDs, b.ko.Spec.SubnetIDs) { + delta.Add("Spec.SubnetIDs", a.ko.Spec.SubnetIDs, b.ko.Spec.SubnetIDs) + } } if !reflect.DeepEqual(a.ko.Spec.SubnetRefs, b.ko.Spec.SubnetRefs) { delta.Add("Spec.SubnetRefs", a.ko.Spec.SubnetRefs, b.ko.Spec.SubnetRefs) diff --git a/test/e2e/bootstrap_resources.py b/test/e2e/bootstrap_resources.py index 8ccaca8..aee47fd 100644 --- a/test/e2e/bootstrap_resources.py +++ b/test/e2e/bootstrap_resources.py @@ -16,23 +16,19 @@ """ from dataclasses import dataclass -from acktest.resources import read_bootstrap_config +from acktest.bootstrapping import Resources +from acktest.bootstrapping.vpc import VPC from e2e import bootstrap_directory -VPC_CIDR_BLOCK = "10.0.81.0/28" -VPC_SUBNET_CIDR_BLOCK = "10.0.81.0/28" @dataclass -class TestBootstrapResources: - VPCID: str - VPCSubnetID: str +class BootstrapResources(Resources): + pass _bootstrap_resources = None -def get_bootstrap_resources(bootstrap_file_name: str = "bootstrap.yaml"): +def get_bootstrap_resources(bootstrap_file_name: str = "bootstrap.pkl") -> BootstrapResources: global _bootstrap_resources if _bootstrap_resources is None: - _bootstrap_resources = TestBootstrapResources( - **read_bootstrap_config(bootstrap_directory, bootstrap_file_name=bootstrap_file_name), - ) - return _bootstrap_resources \ No newline at end of file + _bootstrap_resources = BootstrapResources.deserialize(bootstrap_directory, bootstrap_file_name=bootstrap_file_name) + return _bootstrap_resources diff --git a/test/e2e/requirements.txt b/test/e2e/requirements.txt index 1701882..1dfc96c 100644 --- a/test/e2e/requirements.txt +++ b/test/e2e/requirements.txt @@ -1 +1 @@ -acktest @ git+https://github.com/aws-controllers-k8s/test-infra.git@955d7831ee374a212250179e95a5f3b75e555fd9 \ No newline at end of file +acktest @ git+https://github.com/aws-controllers-k8s/test-infra.git@441e21f888c20d6207a1fb813e4c6848128f3043 \ No newline at end of file diff --git a/test/e2e/service_bootstrap.py b/test/e2e/service_bootstrap.py index 94697d9..befd7a8 100644 --- a/test/e2e/service_bootstrap.py +++ b/test/e2e/service_bootstrap.py @@ -10,100 +10,22 @@ # 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. -"""Bootstraps the resources required to run the AmazonMQ integration tests. +"""Bootstraps the resources required to run the MQ integration tests. """ -import boto3 import logging -import time +from time import sleep -from acktest import resources -from acktest.aws.identity import get_account_id, get_region -from acktest.aws.s3 import duplicate_bucket_contents -from acktest.resources import random_suffix_name +from acktest.bootstrapping.vpc import VPC from e2e import bootstrap_directory -from e2e.bootstrap_resources import ( - TestBootstrapResources, - VPC_CIDR_BLOCK, - VPC_SUBNET_CIDR_BLOCK, -) - - -def create_vpc() -> str: - region = get_region() - ec2 = boto3.client("ec2", region_name=region) - - logging.debug(f"Creating VPC with CIDR {VPC_CIDR_BLOCK}") - - resp = ec2.create_vpc( - CidrBlock=VPC_CIDR_BLOCK, - ) - vpc_id = resp['Vpc']['VpcId'] - - # TODO(jaypipes): Put a proper waiter here... - time.sleep(3) - - vpcs = ec2.describe_vpcs(VpcIds=[vpc_id]) - if len(vpcs['Vpcs']) != 1: - raise RuntimeError( - f"failed to describe VPC we just created '{vpc_id}'", - ) - - vpc = vpcs['Vpcs'][0] - vpc_state = vpc['State'] - if vpc_state != "available": - raise RuntimeError( - f"VPC we just created '{vpc_id}' is not available. current state: {vpc_state}", - ) - - logging.info(f"Created VPC {vpc_id}") - - return vpc_id - - -def create_subnet(vpc_id: str) -> str: - region = get_region() - ec2 = boto3.client("ec2", region_name=region) - - resp = ec2.create_subnet( - CidrBlock=VPC_SUBNET_CIDR_BLOCK, - VpcId=vpc_id, - ) - subnet_id = resp['Subnet']['SubnetId'] - - # TODO(jaypipes): Put a proper waiter here... - time.sleep(3) - - subnets = ec2.describe_subnets(SubnetIds=[subnet_id]) - if len(subnets['Subnets']) != 1: - raise RuntimeError( - f"failed to describe subnet we just created '{subnet_id}'", - ) - - subnet = subnets['Subnets'][0] - subnet_state = subnet['State'] - if subnet_state != "available": - raise RuntimeError( - f"Subnet we just created '{subnet_id}' is not available. current state: {subnet_state}", - ) - - logging.info(f"Created VPC Subnet {subnet_id}") - - return subnet_id - +from e2e.bootstrap_resources import BootstrapResources def service_bootstrap() -> dict: logging.getLogger().setLevel(logging.INFO) - vpc_id = create_vpc() - subnet_id = create_subnet(vpc_id) - - return TestBootstrapResources( - vpc_id, - subnet_id, - ).__dict__ + resources = BootstrapResources() + return resources if __name__ == "__main__": config = service_bootstrap() - # Write config to current directory by default - resources.write_bootstrap_config(config, bootstrap_directory) \ No newline at end of file + config.serialize(bootstrap_directory) \ No newline at end of file diff --git a/test/e2e/service_cleanup.py b/test/e2e/service_cleanup.py index fb1485e..c990259 100644 --- a/test/e2e/service_cleanup.py +++ b/test/e2e/service_cleanup.py @@ -10,55 +10,19 @@ # 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. - -"""Cleans up the resources created by the bootstrapping process. +"""Cleans up the resources created by the MQ bootstrapping process. """ -import boto3 import logging -from acktest import resources -from acktest.aws.identity import get_region +from acktest.bootstrapping import Resources from e2e import bootstrap_directory -from e2e.bootstrap_resources import TestBootstrapResources - - -def delete_subnet(subnet_id: str): - region = get_region() - ec2 = boto3.client("ec2", region_name=region) - - ec2.delete_subnet(SubnetId=subnet_id) - - logging.info(f"Deleted VPC Subnet {subnet_id}") - - -def delete_vpc(vpc_id: str): - region = get_region() - ec2 = boto3.client("ec2", region_name=region) - ec2.delete_vpc(VpcId=vpc_id) - - logging.info(f"Deleted VPC {vpc_id}") - - -def service_cleanup(config: dict): +def service_cleanup(): logging.getLogger().setLevel(logging.INFO) - - resources = TestBootstrapResources( - **config - ) - - try: - delete_subnet(resources.VPCSubnetID) - except: - logging.exception(f"Unable to delete VPC subnet {resources.VPCSubnetID}") - - try: - delete_vpc(resources.VPCID) - except: - logging.exception(f"Unable to delete VPC {resources.VPCID}") + resources = Resources.deserialize(bootstrap_directory) + resources.cleanup() if __name__ == "__main__": - bootstrap_config = resources.read_bootstrap_config(bootstrap_directory) - service_cleanup(bootstrap_config) \ No newline at end of file + service_cleanup() \ No newline at end of file diff --git a/test/e2e/tests/test_broker.py b/test/e2e/tests/test_broker.py index 8ad58e2..f1b739a 100644 --- a/test/e2e/tests/test_broker.py +++ b/test/e2e/tests/test_broker.py @@ -24,6 +24,7 @@ from acktest.resources import random_suffix_name from acktest.k8s import resource as k8s +from e2e.bootstrap_resources import get_bootstrap_resources from e2e import service_marker, CRD_GROUP, CRD_VERSION, load_mq_resource from e2e.replacement_values import REPLACEMENT_VALUES