Skip to content

Commit a134860

Browse files
pull docker images from ghcr and fallback to docker if necessary (#926)
* pulling images from ghcr by default Signed-off-by: Pravin Pushkar <[email protected]> * fixing self_hosted e2e tests Signed-off-by: Pravin Pushkar <[email protected]> * default all tests with ghcr and removing tests for --image-registry Signed-off-by: Pravin Pushkar <[email protected]> * adding tests for dockerhub install and custom registry Signed-off-by: Pravin Pushkar <[email protected]> * fixing review comments Signed-off-by: Pravin Pushkar <[email protected]> * Fixing review comments Signed-off-by: Pravin Pushkar <[email protected]> * Review comments fix Signed-off-by: Pravin Pushkar <[email protected]> * Some refactoring Signed-off-by: Pravin Pushkar <[email protected]> * fix for review comments Signed-off-by: Pravin Pushkar <[email protected]>
1 parent 4818533 commit a134860

File tree

7 files changed

+153
-56
lines changed

7 files changed

+153
-56
lines changed

.github/workflows/self_hosted_e2e.yaml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ on:
2020
- release-*
2121
schedule:
2222
- cron: '0 */3 * * *'
23+
- cron: '0 0 * * *'
2324
pull_request:
2425
branches:
2526
- master
@@ -37,7 +38,6 @@ jobs:
3738
ARCHIVE_OUTDIR: dist/archives
3839
DAPR_RUNTIME_VERSION: "1.6.0"
3940
DAPR_DASHBOARD_VERSION: 0.9.0
40-
CUSTOM_IMAGE_REGISTRY: docker.io
4141
strategy:
4242
matrix:
4343
os: [ubuntu-latest, macos-latest]
@@ -76,7 +76,19 @@ jobs:
7676
echo "DAPR_DASHBOARD_VERSION=$DASHBOARD_VERSION" >> $GITHUB_ENV
7777
echo "Found $DASHBOARD_VERSION"
7878
shell: bash
79-
- name: Run E2E tests
79+
- name: Run E2E tests with GHCR
80+
if: github.event.schedule != '0 0 * * *'
81+
run: |
82+
export TEST_OUTPUT_FILE=$GITHUB_WORKSPACE/test-e2e-standalone.json
83+
echo "TEST_OUTPUT_FILE=$TEST_OUTPUT_FILE" >> $GITHUB_ENV
84+
export GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
85+
make e2e-build-run-sh
86+
shell: bash
87+
- name: Run E2E tests with Docker hub
88+
# only runs once in a day
89+
if: github.event.schedule == '0 0 * * *'
90+
env:
91+
DAPR_DEFAULT_IMAGE_REGISTRY: dockerhub
8092
run: |
8193
export TEST_OUTPUT_FILE=$GITHUB_WORKSPACE/test-e2e-standalone.json
8294
echo "TEST_OUTPUT_FILE=$TEST_OUTPUT_FILE" >> $GITHUB_ENV

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,12 @@ Runtime version: v1.0.0
129129
```
130130
#### Install by providing a docker container registry url
131131

132-
You can install Dapr runtime by pulling docker images from a given registry url by using `--image-repository` flag.
132+
You can install Dapr runtime by pulling docker images from a given private registry uri by using `--image-registry` flag.
133+
> Note: This command expects that images have been hosted like example.io/<username>/dapr/dapr:<tag>, example.io/<username>/dapr/3rdparty/redis:<tag>, example.io/<username>/dapr/3rdparty/zipkin:<tag>
133134
134135
```bash
135-
$ dapr init --image-repository <registry-url>
136+
# Example of pulling images from a private registry.
137+
$ dapr init --image-registry example.io/<username>
136138
```
137139

138140
#### Install to a specific Docker network

cmd/init.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,14 @@ var InitCmd = &cobra.Command{
4646
Short: "Install Dapr on supported hosting platforms. Supported platforms: Kubernetes and self-hosted",
4747
PreRun: func(cmd *cobra.Command, args []string) {
4848
viper.BindPFlag("network", cmd.Flags().Lookup("network"))
49-
viper.BindPFlag("image-repository", cmd.Flags().Lookup("image-repository"))
49+
viper.BindPFlag("image-registry", cmd.Flags().Lookup("image-registry"))
5050
},
5151
Example: `
5252
# Initialize Dapr in self-hosted mode
5353
dapr init
5454
55-
#Initialize Dapr in self-hosted mode with a provided docker image repository. Image looked up as <repository-url>/<image>
56-
dapr init --image-repository <repository-url>
55+
#Initialize Dapr in self-hosted mode with a provided docker image registry. Image looked up as <registry-url>/<image>
56+
dapr init --image-registry <registry-url>
5757
5858
# Initialize Dapr in Kubernetes
5959
dapr init -k
@@ -98,15 +98,18 @@ dapr init --from-dir <path-to-directory>
9898
print.SuccessStatusEvent(os.Stdout, fmt.Sprintf("Success! Dapr has been installed to namespace %s. To verify, run `dapr status -k' in your terminal. To get started, go here: https://aka.ms/dapr-getting-started", config.Namespace))
9999
} else {
100100
dockerNetwork := ""
101-
imageRepositoryURL := ""
101+
imageRegistryURL := ""
102102
if !slimMode {
103103
dockerNetwork = viper.GetString("network")
104-
imageRepositoryURL = viper.GetString("image-repository")
104+
imageRegistryURL = viper.GetString("image-registry")
105105
}
106106
if fromDir != "" {
107107
print.WarningStatusEvent(os.Stdout, "Local bundle installation using from-dir flag is currently a preview feature.")
108108
}
109-
err := standalone.Init(runtimeVersion, dashboardVersion, dockerNetwork, slimMode, imageRepositoryURL, fromDir)
109+
if imageRegistryURL != "" {
110+
print.WarningStatusEvent(os.Stdout, "Flag --image-registry is a preview feature and is subject to change. It is only available from CLI version 1.7 onwards.")
111+
}
112+
err := standalone.Init(runtimeVersion, dashboardVersion, dockerNetwork, slimMode, imageRegistryURL, fromDir)
110113
if err != nil {
111114
print.FailureStatusEvent(os.Stderr, err.Error())
112115
os.Exit(1)
@@ -142,6 +145,6 @@ func init() {
142145
InitCmd.Flags().StringVarP(&fromDir, "from-dir", "", "", "Use Dapr artifacts from local directory instead of from network to init")
143146
InitCmd.Flags().BoolP("help", "h", false, "Print this help message")
144147
InitCmd.Flags().StringArrayVar(&values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
145-
InitCmd.Flags().String("image-repository", "", "Custom/Private docker image repository url")
148+
InitCmd.Flags().String("image-registry", "", "Custom/Private docker image repository url")
146149
RootCmd.AddCommand(InitCmd)
147150
}

pkg/standalone/docker.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,12 @@ func imageFileName(image string) string {
127127
filename = strings.ReplaceAll(filename, ":", "-")
128128
return filename
129129
}
130+
131+
func TryPullImage(imageName string) bool {
132+
args := []string{
133+
"pull",
134+
imageName,
135+
}
136+
_, err := utils.RunCmdAndWait("docker", args...)
137+
return err == nil
138+
}

pkg/standalone/standalone.go

Lines changed: 79 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ const (
5151
redisDockerImageName = "redislabs/rejson"
5252
zipkinDockerImageName = "openzipkin/zipkin"
5353

54+
githubContainerRegistryName = "ghcr"
55+
ghcrURI = "ghcr.io/dapr"
56+
daprGhcrImageName = "dapr"
57+
dockerContainerRegistryName = "dockerhub"
58+
redisGhcrImageName = "3rdparty/redis"
59+
zipkinGhcrImageName = "3rdparty/zipkin"
60+
5461
// DaprPlacementContainerName is the container name of placement service.
5562
DaprPlacementContainerName = "dapr_placement"
5663
// DaprRedisContainerName is the container name of redis.
@@ -64,6 +71,11 @@ const (
6471
dockerImageSubDir = "docker"
6572
)
6673

74+
var (
75+
defaultImageRegistryName string
76+
privateRegTemplateString = "%s/dapr/%s"
77+
)
78+
6779
type configuration struct {
6880
APIVersion string `yaml:"apiVersion"`
6981
Kind string `yaml:"kind"`
@@ -99,12 +111,12 @@ type componentMetadataItem struct {
99111
}
100112

101113
type initInfo struct {
102-
fromDir string
103-
slimMode bool
104-
runtimeVersion string
105-
dashboardVersion string
106-
dockerNetwork string
107-
imageRepositoryURL string
114+
fromDir string
115+
slimMode bool
116+
runtimeVersion string
117+
dashboardVersion string
118+
dockerNetwork string
119+
imageRegistryURL string
108120
}
109121

110122
// Check if the previous version is already installed.
@@ -120,16 +132,20 @@ func isBinaryInstallationRequired(binaryFilePrefix, installDir string) (bool, er
120132
}
121133

122134
// Init installs Dapr on a local machine using the supplied runtimeVersion.
123-
func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMode bool, imageRepositoryURL string, fromDir string) error {
135+
func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMode bool, imageRegistryURL string, fromDir string) error {
136+
var err error
124137
if !slimMode {
125138
dockerInstalled := utils.IsDockerInstalled()
126139
if !dockerInstalled {
127140
return errors.New("could not connect to Docker. Docker may not be installed or running")
128141
}
142+
defaultImageRegistryName, err = utils.GetDefaultRegistry(githubContainerRegistryName, dockerContainerRegistryName)
143+
if err != nil {
144+
return err
145+
}
129146
}
130147

131148
if runtimeVersion == latestVersion && fromDir == "" {
132-
var err error
133149
runtimeVersion, err = cli_ver.GetDaprVersion()
134150
if err != nil {
135151
return fmt.Errorf("cannot get the latest release version: '%w'. Try specifying --runtime-version=<desired_version>", err)
@@ -139,7 +155,6 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod
139155
print.InfoStatusEvent(os.Stdout, "Installing runtime version %s", runtimeVersion)
140156

141157
if dashboardVersion == latestVersion && fromDir == "" {
142-
var err error
143158
dashboardVersion, err = cli_ver.GetDashboardVersion()
144159
if err != nil {
145160
print.WarningStatusEvent(os.Stdout, "cannot get the latest dashboard version: '%s'. Try specifying --dashboard-version=<desired_version>", err)
@@ -157,7 +172,7 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod
157172
}
158173

159174
daprBinDir := defaultDaprBinPath()
160-
err := prepareDaprInstallDir(daprBinDir)
175+
err = prepareDaprInstallDir(daprBinDir)
161176
if err != nil {
162177
return err
163178
}
@@ -197,12 +212,12 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod
197212
}
198213

199214
info := initInfo{
200-
fromDir: fromDir,
201-
slimMode: slimMode,
202-
runtimeVersion: runtimeVersion,
203-
dashboardVersion: dashboardVersion,
204-
dockerNetwork: dockerNetwork,
205-
imageRepositoryURL: imageRepositoryURL,
215+
fromDir: fromDir,
216+
slimMode: slimMode,
217+
runtimeVersion: runtimeVersion,
218+
dashboardVersion: dashboardVersion,
219+
dockerNetwork: dockerNetwork,
220+
imageRegistryURL: imageRegistryURL,
206221
}
207222
for _, step := range initSteps {
208223
// Run init on the configurations and containers.
@@ -268,13 +283,22 @@ func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) {
268283
}
269284
args := []string{}
270285

286+
var imageName string
287+
271288
if exists {
272289
// do not create container again if it exists.
273290
args = append(args, "start", zipkinContainerName)
274291
} else {
275-
imageName := zipkinDockerImageName
276-
if info.imageRepositoryURL != "" {
277-
imageName = fmt.Sprintf("%s/%s", info.imageRepositoryURL, imageName)
292+
if info.imageRegistryURL != "" && info.imageRegistryURL != ghcrURI && info.imageRegistryURL != "docker.io" {
293+
imageName = fmt.Sprintf(privateRegTemplateString, info.imageRegistryURL, zipkinGhcrImageName)
294+
} else if defaultImageRegistryName == githubContainerRegistryName && info.imageRegistryURL == "" {
295+
imageName = fmt.Sprintf("%s/%s", ghcrURI, zipkinGhcrImageName)
296+
} else if defaultImageRegistryName == dockerContainerRegistryName && info.imageRegistryURL == "" {
297+
imageName = zipkinDockerImageName
298+
} else {
299+
err = fmt.Errorf("either %s or Env variable %s not set properly", "--image-registry", "DAPR_DEFAULT_IMAGE_REGISTRY")
300+
errorChan <- err
301+
return
278302
}
279303

280304
args = append(args,
@@ -327,13 +351,21 @@ func runRedis(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) {
327351
}
328352
args := []string{}
329353

354+
var imageName string
330355
if exists {
331356
// do not create container again if it exists.
332357
args = append(args, "start", redisContainerName)
333358
} else {
334-
imageName := redisDockerImageName
335-
if info.imageRepositoryURL != "" {
336-
imageName = fmt.Sprintf("%s/%s", info.imageRepositoryURL, imageName)
359+
if info.imageRegistryURL != "" && info.imageRegistryURL != ghcrURI && info.imageRegistryURL != "docker.io" {
360+
imageName = fmt.Sprintf(privateRegTemplateString, info.imageRegistryURL, redisGhcrImageName)
361+
} else if defaultImageRegistryName == githubContainerRegistryName && info.imageRegistryURL == "" {
362+
imageName = fmt.Sprintf("%s/%s", ghcrURI, redisGhcrImageName)
363+
} else if defaultImageRegistryName == dockerContainerRegistryName && info.imageRegistryURL == "" {
364+
imageName = redisDockerImageName
365+
} else {
366+
err = fmt.Errorf("either %s or Env variable %s not set properly", "--image-registry", "DAPR_DEFAULT_IMAGE_REGISTRY")
367+
errorChan <- err
368+
return
337369
}
338370

339371
args = append(args,
@@ -378,14 +410,24 @@ func runPlacementService(wg *sync.WaitGroup, errorChan chan<- error, info initIn
378410

379411
placementContainerName := utils.CreateContainerName(DaprPlacementContainerName, info.dockerNetwork)
380412

381-
image := fmt.Sprintf("%s:%s", daprDockerImageName, info.runtimeVersion)
382-
if info.imageRepositoryURL != "" {
383-
image = fmt.Sprintf("%s/%s", info.imageRepositoryURL, image)
384-
}
385-
386-
// Use only image for latest version.
387-
if info.runtimeVersion == latestVersion {
388-
image = daprDockerImageName
413+
var image string
414+
415+
if info.imageRegistryURL != "" && info.imageRegistryURL != ghcrURI && info.imageRegistryURL != "docker.io" {
416+
image = getPlacementImageWithTag(daprGhcrImageName, info.runtimeVersion)
417+
image = fmt.Sprintf(privateRegTemplateString, info.imageRegistryURL, image)
418+
} else if defaultImageRegistryName == githubContainerRegistryName && info.imageRegistryURL == "" {
419+
image = getPlacementImageWithTag(daprGhcrImageName, info.runtimeVersion)
420+
image = fmt.Sprintf("%s/%s", ghcrURI, image)
421+
if !TryPullImage(image) {
422+
print.InfoStatusEvent(os.Stdout, "Placement image not found in Github container registry, pulling it from Docker Hub")
423+
image = getPlacementImageWithTag(daprDockerImageName, info.runtimeVersion)
424+
}
425+
} else if defaultImageRegistryName == dockerContainerRegistryName && info.imageRegistryURL == "" {
426+
image = getPlacementImageWithTag(daprDockerImageName, info.runtimeVersion)
427+
} else {
428+
err := fmt.Errorf("either %s or Env variable %s not set properly", "--image-registry", "DAPR_DEFAULT_IMAGE_REGISTRY")
429+
errorChan <- err
430+
return
389431
}
390432

391433
exists, err := confirmContainerIsRunningOrExists(placementContainerName, false)
@@ -1013,3 +1055,10 @@ func parseVersionFile(fromDir string) (string, string) {
10131055

10141056
return versions[daprRuntimeFilePrefix], versions[dashboardFilePrefix]
10151057
}
1058+
1059+
func getPlacementImageWithTag(name, version string) string {
1060+
if version == latestVersion {
1061+
return name
1062+
}
1063+
return fmt.Sprintf("%s:%s", name, version)
1064+
}

tests/e2e/standalone/standalone_test.go

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,8 @@ import (
4141
)
4242

4343
var (
44-
daprRuntimeVersion = os.Getenv("DAPR_RUNTIME_VERSION")
45-
daprDashboardVersion = os.Getenv("DAPR_DASHBOARD_VERSION")
46-
dockerImageCustomRegistry = os.Getenv("CUSTOM_IMAGE_REGISTRY")
44+
daprRuntimeVersion = os.Getenv("DAPR_RUNTIME_VERSION")
45+
daprDashboardVersion = os.Getenv("DAPR_DASHBOARD_VERSION")
4746
)
4847

4948
var socketCases = []string{"", "/tmp"}
@@ -57,7 +56,6 @@ func TestStandaloneInstall(t *testing.T) {
5756
phase func(*testing.T)
5857
}{
5958
{"test install", testInstall},
60-
{"test install from custom registry", testInstallWithCustomImageRegsitry},
6159
{"test run log json enabled", testRunLogJSON},
6260
{"test run", testRun},
6361
{"test stop", testStop},
@@ -136,6 +134,22 @@ func TestNegativeScenarios(t *testing.T) {
136134
})
137135
}
138136

137+
func TestPrivateRegistry(t *testing.T) {
138+
// Ensure a clean environment.
139+
uninstall()
140+
141+
tests := []struct {
142+
name string
143+
phase func(*testing.T)
144+
}{
145+
{"test install fails", testInstallWithPrivateRegsitry},
146+
}
147+
148+
for _, tc := range tests {
149+
t.Run(tc.name, tc.phase)
150+
}
151+
}
152+
139153
func getDaprPath() string {
140154
distDir := fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)
141155

@@ -195,19 +209,11 @@ func testInstall(t *testing.T) {
195209
verifyArtifactsAfterInstall(t)
196210
}
197211

198-
func testInstallWithCustomImageRegsitry(t *testing.T) {
199-
if dockerImageCustomRegistry == "" {
200-
t.Skip("Custom image registry is not set, skipping the test for now..")
201-
}
202-
// Uninstall the previously installed Dapr
203-
uninstall()
212+
func testInstallWithPrivateRegsitry(t *testing.T) {
204213
daprPath := getDaprPath()
205-
output, err := spawn.Command(daprPath, "init", "--runtime-version", daprRuntimeVersion, "--image-repository", dockerImageCustomRegistry, "--log-as-json")
214+
output, err := spawn.Command(daprPath, "init", "--runtime-version", daprRuntimeVersion, "--image-registry", "smplregistry.io/owner", "--log-as-json")
206215
t.Log(output)
207-
require.NoError(t, err, "init failed")
208-
209-
// verify all artifacts after successfull install
210-
verifyArtifactsAfterInstall(t)
216+
require.Error(t, err, "init failed")
211217
}
212218

213219
func verifyArtifactsAfterInstall(t *testing.T) {

0 commit comments

Comments
 (0)