Skip to content

Commit 11577da

Browse files
committed
Merge commit '4052c80dc3f7' into release/v2.12-ent
2 parents 3e063c6 + 4052c80 commit 11577da

File tree

49 files changed

+2032
-478
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2032
-478
lines changed
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
name: Create Rancher PR
2+
3+
# This workflow triggers on a push to the main branch. It updates the
4+
# rancher/shepherd dependency in the rancher/rancher repository and opens a PR.
5+
on:
6+
push:
7+
branches:
8+
- release/v2.12
9+
env:
10+
INPUT_SOURCE_URL: ${{ github.event.inputs.source_url }}
11+
INPUT_SOURCE_AUTHOR: ${{ github.event.inputs.source_author }}
12+
13+
jobs:
14+
create-rancher-pr:
15+
permissions:
16+
# This is required for the vault action to get an OIDC token
17+
id-token: write
18+
# This is required to checkout the repository
19+
contents: read
20+
runs-on: ubuntu-latest
21+
steps:
22+
# Checkout the current repo (shepherd) to get the commit SHA
23+
- name: Checkout shepherd
24+
uses: actions/checkout@v4
25+
26+
- name: Get short SHA
27+
id: sha
28+
run: echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
29+
30+
- name: Retrieve token from vault
31+
uses: rancher-eio/read-vault-secrets@main
32+
with:
33+
secrets: |
34+
github/token/rancher--rancher--pull_requests--write token | GH_TOKEN
35+
36+
# Checkout the target repo (rancher/rancher) where the PR will be created
37+
- name: Checkout rancher/rancher
38+
uses: actions/checkout@v4
39+
with:
40+
repository: rancher/rancher
41+
path: rancher
42+
ref: release/v2.12
43+
token: ${{ env.GH_TOKEN }}
44+
45+
- name: Setup Go
46+
uses: actions/setup-go@v5
47+
with:
48+
go-version-file: 'rancher/go.mod'
49+
50+
- name: Create branch, update, and push changes
51+
id: update_and_push
52+
working-directory: ./rancher
53+
run: |
54+
BRANCH_NAME="shepherd-githubaction-$(date +%Y-%m-%d-%H-%M-%S)-2.12"
55+
echo "branch_name=${BRANCH_NAME}" >> $GITHUB_OUTPUT
56+
57+
git config user.name "github-actions[bot]"
58+
git config user.email "github-actions[bot]@users.noreply.github.com"
59+
60+
echo "Creating and switching to new branch: ${BRANCH_NAME}"
61+
git checkout -b ${BRANCH_NAME}
62+
63+
echo "Updating rancher/shepherd to commit ${{ github.sha }}"
64+
go get github.com/rancher/shepherd@${{ github.sha }}
65+
go mod tidy
66+
67+
# Check for changes
68+
if [[ -z $(git status --porcelain) ]]; then
69+
echo "No changes to commit."
70+
echo "changes_exist=false" >> $GITHUB_ENV
71+
else
72+
echo "Changes detected. Committing and pushing."
73+
echo "changes_exist=true" >> $GITHUB_ENV
74+
git add go.mod go.sum
75+
git commit -m "shepherd-githubaction: Update rancher/shepherd to ${{ steps.sha.outputs.short_sha }}"
76+
git push origin ${BRANCH_NAME}
77+
fi
78+
- name: Create Pull Request
79+
if: env.changes_exist == 'true'
80+
id: cpr
81+
uses: actions/github-script@v7
82+
with:
83+
github-token: ${{ env.GH_TOKEN }}
84+
script: |
85+
const source_author = process.env.INPUT_SOURCE_AUTHOR || context.actor;
86+
let body = 'Auto-generated by Shepherd GitHub Actions This PR updates the \`rancher/shepherd\` dependency to the latest version. Please delete the branch after merge.\n\n'
87+
if ( `${ process.env.INPUT_SOURCE_URL }` ) {
88+
body += `\nSource URL: ${ process.env.INPUT_SOURCE_URL }`
89+
}
90+
if ( `${ process.env.INPUT_SOURCE_AUTHOR }` ) {
91+
body += `\nSource AUTHOR: @${ process.env.INPUT_SOURCE_AUTHOR}`
92+
}
93+
94+
const { data: pr } = await github.rest.pulls.create({
95+
title: "[v2.12] shepherd-githubaction: Update rancher/shepherd to latest version",
96+
body: body,
97+
owner: "rancher",
98+
repo: "rancher",
99+
base: "release/v2.12",
100+
head: "${{ steps.update_and_push.outputs.branch_name }}"
101+
});
102+
await github.rest.issues.addLabels({
103+
owner: "rancher",
104+
repo: "rancher",
105+
issue_number: pr.number,
106+
labels: ["automation", "status/auto-created"],
107+
});
108+
// Also assign the person who triggered the workflow to the PR for visibility
109+
await github.rest.issues.addAssignees({
110+
owner: "rancher",
111+
repo: "rancher",
112+
issue_number: pr.number,
113+
assignees: [source_author],
114+
});
115+
// Request reviewers for the pull request
116+
await github.rest.pulls.requestReviewers({
117+
owner: "rancher",
118+
repo: "rancher",
119+
pull_number: pr.number,
120+
reviewers: ["hamistao", "slickwarren", "Priyashetty17"],
121+
});
122+
console.log(`Created new pull request: ${pr.html_url}`);
123+
return pr.html_url;
124+
125+
- name: Check outputs
126+
if: env.changes_exist == 'true'
127+
run: |
128+
echo "Pull Request URL - ${{ steps.cpr.outputs.result }}"

clients/harvester/client.go

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99

1010
"github.com/rancher/shepherd/pkg/clientbase"
1111
"github.com/rancher/shepherd/pkg/config"
12-
"github.com/rancher/shepherd/pkg/environmentflag"
1312
"github.com/rancher/shepherd/pkg/session"
1413
"k8s.io/client-go/dynamic"
1514
"k8s.io/client-go/rest"
@@ -36,32 +35,44 @@ func NewClient(bearerToken string, session *session.Session) (*Client, error) {
3635
harvesterConfig := new(Config)
3736
config.LoadConfig(ConfigurationFileKey, harvesterConfig)
3837

39-
environmentFlags := environmentflag.NewEnvironmentFlags()
40-
environmentflag.LoadEnvironmentFlags(environmentflag.ConfigurationFileKey, environmentFlags)
38+
c, err := NewClientForConfig(bearerToken, harvesterConfig, session)
39+
if err != nil {
40+
return nil, err
41+
}
42+
43+
return c, err
44+
}
4145

46+
// NewClientForConfig is the constructor for initializing a rancher Client for the given config and session.
47+
func NewClientForConfig(bearerToken string, harvesterConfig *Config, session *session.Session) (*Client, error) {
4248
if bearerToken == "" {
4349
bearerToken = harvesterConfig.AdminToken
4450
}
4551

52+
if harvesterConfig == nil {
53+
harvesterConfig = new(Config)
54+
}
55+
4656
c := &Client{
4757
HarvesterConfig: harvesterConfig,
4858
}
4959

50-
session.CleanupEnabled = *harvesterConfig.Cleanup
60+
if session != nil {
61+
session.CleanupEnabled = *c.HarvesterConfig.Cleanup
62+
}
5163

5264
var err error
53-
restConfig := newRestConfig(bearerToken, harvesterConfig)
54-
c.restConfig = restConfig
65+
c.restConfig = newRestConfig(bearerToken, c.HarvesterConfig)
5566
c.Session = session
5667

57-
c.Steve, err = v1.NewClient(clientOptsV1(restConfig, c.HarvesterConfig))
68+
c.Steve, err = v1.NewClient(clientOptsV1(c.restConfig, c.HarvesterConfig))
5869
if err != nil {
5970
return nil, err
6071
}
6172

6273
c.Steve.Ops.Session = session
6374

64-
catalogClient, err := catalog.NewForConfig(restConfig, session)
75+
catalogClient, err := catalog.NewForConfig(c.restConfig, session)
6576
if err != nil {
6677
return nil, err
6778
}
@@ -71,7 +82,7 @@ func NewClient(bearerToken string, session *session.Session) (*Client, error) {
7182
return c, nil
7283
}
7384

74-
// newRestConfig is a constructor that sets ups rest.Config the configuration used by the Provisioning client.
85+
// newRestConfig is a constructor that sets up a rest.Config the configuration used by the Provisioning client.
7586
func newRestConfig(bearerToken string, harvesterConfig *Config) *rest.Config {
7687
return &rest.Config{
7788
Host: harvesterConfig.Host,
@@ -82,7 +93,7 @@ func newRestConfig(bearerToken string, harvesterConfig *Config) *rest.Config {
8293
}
8394
}
8495

85-
// clientOptsV1 is a constructor that sets ups clientbase.ClientOpts the configuration used by the v1 harvester clients.
96+
// clientOptsV1 is a constructor that sets up a clientbase.ClientOpts the configuration used by the v1 harvester clients.
8697
func clientOptsV1(restConfig *rest.Config, harvesterConfig *Config) *clientbase.ClientOpts {
8798
return &clientbase.ClientOpts{
8899
URL: fmt.Sprintf("https://%s/v1", harvesterConfig.Host),
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package activedirectory
2+
3+
import (
4+
"fmt"
5+
6+
apisv3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"
7+
management "github.com/rancher/shepherd/clients/rancher/generated/management/v3"
8+
"github.com/rancher/shepherd/pkg/config"
9+
"github.com/rancher/shepherd/pkg/session"
10+
)
11+
12+
type Operations interface {
13+
Enable() error
14+
Disable() error
15+
Update(existing, updates *management.AuthConfig) (*management.AuthConfig, error)
16+
}
17+
18+
const (
19+
resourceType = "activedirectory"
20+
schemaType = "activeDirectoryConfigs"
21+
)
22+
23+
type Client struct {
24+
client *management.Client
25+
session *session.Session
26+
Config *Config
27+
}
28+
29+
// NewActiveDirectory constructs ActiveDirectory struct after it reads Active Directory from the configuration file
30+
func NewActiveDirectory(client *management.Client, session *session.Session) (*Client, error) {
31+
adConfig := new(Config)
32+
config.LoadConfig(ConfigurationFileKey, adConfig)
33+
34+
return &Client{
35+
client: client,
36+
session: session,
37+
Config: adConfig,
38+
}, nil
39+
}
40+
41+
// Enable is a method of ActiveDirectory, makes a request to the action with the given
42+
// configuration values
43+
func (a *Client) Enable() error {
44+
var jsonResp map[string]interface{}
45+
url := a.newActionURL("testAndApply")
46+
47+
enableActionInput, err := a.newEnableInputFromConfig()
48+
if err != nil {
49+
return err
50+
}
51+
52+
err = a.client.Ops.DoModify("POST", url, enableActionInput, &jsonResp)
53+
if err != nil {
54+
return err
55+
}
56+
57+
a.session.RegisterCleanupFunc(func() error {
58+
return a.Disable()
59+
})
60+
61+
return nil
62+
}
63+
64+
// Update is a method of ActiveDirectory, makes an update with the given configuration values
65+
func (a *Client) Update(
66+
existing, updates *management.AuthConfig,
67+
) (*management.AuthConfig, error) {
68+
return a.client.AuthConfig.Update(existing, updates)
69+
}
70+
71+
// Disable is a method of ActiveDirectory, makes a request to disable Active Directory
72+
func (a *Client) Disable() error {
73+
var jsonResp map[string]any
74+
url := a.newActionURL("disable")
75+
disableActionInput := a.newDisableInput()
76+
77+
return a.client.Ops.DoModify("POST", url, &disableActionInput, &jsonResp)
78+
}
79+
80+
func (a *Client) newActionURL(action string) string {
81+
return fmt.Sprintf(
82+
"%v/%v/%v?action=%v",
83+
a.client.Opts.URL,
84+
schemaType,
85+
resourceType,
86+
action,
87+
)
88+
}
89+
90+
func (a *Client) newEnableInputFromConfig() (*apisv3.ActiveDirectoryTestAndApplyInput, error) {
91+
var server string
92+
93+
if a.Config.Hostname == "" && a.Config.IP == "" {
94+
return nil, fmt.Errorf("active Directory Hostname and IP are empty, please provide one of them")
95+
}
96+
97+
server = a.Config.Hostname
98+
if server == "" {
99+
server = a.Config.IP
100+
}
101+
102+
if a.Config.Users.Admin.Username == "" || a.Config.Users.Admin.Password == "" {
103+
return nil, fmt.Errorf("admin username or password are empty, please provide them")
104+
}
105+
106+
// Create the nested ActiveDirectoryConfig
107+
adConfig := &apisv3.ActiveDirectoryConfig{
108+
AuthConfig: apisv3.AuthConfig{
109+
AccessMode: a.Config.AccessMode,
110+
},
111+
Servers: []string{server},
112+
Port: int64(a.Config.Port),
113+
TLS: a.Config.TLS,
114+
StartTLS: a.Config.StartTLS,
115+
ServiceAccountUsername: a.Config.ServiceAccount.DistinguishedName,
116+
ServiceAccountPassword: a.Config.ServiceAccount.Password,
117+
UserSearchBase: a.Config.Users.SearchBase,
118+
UserObjectClass: a.Config.Users.ObjectClass,
119+
UserNameAttribute: a.Config.Users.UsernameAttribute,
120+
UserLoginAttribute: a.Config.Users.LoginAttribute,
121+
UserSearchAttribute: a.Config.Users.SearchAttribute,
122+
UserSearchFilter: a.Config.Users.SearchFilter,
123+
UserEnabledAttribute: a.Config.Users.EnabledAttribute,
124+
UserDisabledBitMask: a.Config.Users.DisabledBitMask,
125+
GroupSearchBase: a.Config.Groups.SearchBase,
126+
GroupObjectClass: a.Config.Groups.ObjectClass,
127+
GroupNameAttribute: a.Config.Groups.NameAttribute,
128+
GroupSearchAttribute: a.Config.Groups.SearchAttribute,
129+
GroupSearchFilter: a.Config.Groups.SearchFilter,
130+
GroupMemberUserAttribute: a.Config.Groups.MemberUserAttribute,
131+
GroupMemberMappingAttribute: a.Config.Groups.MemberMappingAttribute,
132+
GroupDNAttribute: a.Config.Groups.DNAttribute,
133+
NestedGroupMembershipEnabled: &a.Config.Groups.NestedGroupMembershipEnabled,
134+
}
135+
136+
// Wrap it in ActiveDirectoryTestAndApplyInput with test credentials
137+
testAndApplyInput := &apisv3.ActiveDirectoryTestAndApplyInput{
138+
ActiveDirectoryConfig: *adConfig,
139+
Username: a.Config.Users.Admin.Username,
140+
Password: a.Config.Users.Admin.Password,
141+
Enabled: true,
142+
}
143+
144+
return testAndApplyInput, nil
145+
}
146+
147+
func (a *Client) newDisableInput() []byte {
148+
return []byte(`{"action": "disable"}`)
149+
}

0 commit comments

Comments
 (0)