diff --git a/config/v3_5_experimental/config.go b/config/v3_5_experimental/config.go deleted file mode 100644 index 9a92bf2ac..000000000 --- a/config/v3_5_experimental/config.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v3_5_experimental - -import ( - "github.com/coreos/ignition/v2/config/merge" - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - prev "github.com/coreos/ignition/v2/config/v3_4" - "github.com/coreos/ignition/v2/config/v3_5_experimental/translate" - "github.com/coreos/ignition/v2/config/v3_5_experimental/types" - "github.com/coreos/ignition/v2/config/validate" - - "github.com/coreos/go-semver/semver" - "github.com/coreos/vcontext/report" -) - -func Merge(parent, child types.Config) types.Config { - res, _ := merge.MergeStructTranscribe(parent, child) - return res.(types.Config) -} - -// Parse parses the raw config into a types.Config struct and generates a report of any -// errors, warnings, info, and deprecations it encountered -func Parse(rawConfig []byte) (types.Config, report.Report, error) { - if len(rawConfig) == 0 { - return types.Config{}, report.Report{}, errors.ErrEmpty - } - - var config types.Config - if rpt, err := util.HandleParseErrors(rawConfig, &config); err != nil { - return types.Config{}, rpt, err - } - - version, err := semver.NewVersion(config.Ignition.Version) - - if err != nil || *version != types.MaxVersion { - return types.Config{}, report.Report{}, errors.ErrUnknownVersion - } - - rpt := validate.ValidateWithContext(config, rawConfig) - if rpt.IsFatal() { - return types.Config{}, rpt, errors.ErrInvalid - } - - return config, rpt, nil -} - -// ParseCompatibleVersion parses the raw config of version 3.5.0-experimental or -// lesser into a 3.5-exp types.Config struct and generates a report of any errors, -// warnings, info, and deprecations it encountered -func ParseCompatibleVersion(raw []byte) (types.Config, report.Report, error) { - version, rpt, err := util.GetConfigVersion(raw) - if err != nil { - return types.Config{}, rpt, err - } - - if version == types.MaxVersion { - return Parse(raw) - } - prevCfg, r, err := prev.ParseCompatibleVersion(raw) - if err != nil { - return types.Config{}, r, err - } - return translate.Translate(prevCfg), r, nil -} diff --git a/config/v3_5_experimental/config_test.go b/config/v3_5_experimental/config_test.go deleted file mode 100644 index a56b4b3a2..000000000 --- a/config/v3_5_experimental/config_test.go +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v3_5_experimental - -import ( - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/v3_5_experimental/types" - "github.com/stretchr/testify/assert" -) - -func TestParse(t *testing.T) { - type in struct { - config []byte - } - type out struct { - config types.Config - err error - } - - tests := []struct { - in in - out out - }{ - { - in: in{config: []byte(`{"ignitionVersion": 1}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "1.0.0"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "2.0.0"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "2.1.0"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "2.2.0"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "2.3.0"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "2.4.0"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.0.0"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.1.0"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.2.0"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.3.0"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.4.0"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "2.0.0-experimental"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "2.1.0-experimental"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "2.2.0-experimental"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "2.3.0-experimental"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "2.4.0-experimental"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "2.5.0-experimental"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.0.0-experimental"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.1.0-experimental"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.2.0-experimental"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.3.0-experimental"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.4.0-experimental"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.5.0-experimental"}}`)}, - out: out{config: types.Config{Ignition: types.Ignition{Version: types.MaxVersion.String()}}}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "2.0.0"},}`)}, - out: out{err: errors.ErrInvalid}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "invalid.semver"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte{}}, - out: out{err: errors.ErrEmpty}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.5.0-experimental"}, "storage": {"filesystems": [{"format": "ext4", "label": "zzzzzzzzzzzzzzzzzzzzzzzzzzz"}]}}`)}, - out: out{err: errors.ErrInvalid}, - }, - } - - testsCompt := []struct { - in in - out out - }{ - { - in: in{config: []byte(`{"ignition": {"version": "3.0.0"}}`)}, - out: out{config: types.Config{Ignition: types.Ignition{Version: types.MaxVersion.String()}}}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.1.0"}}`)}, - out: out{config: types.Config{Ignition: types.Ignition{Version: types.MaxVersion.String()}}}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.2.0"}}`)}, - out: out{config: types.Config{Ignition: types.Ignition{Version: types.MaxVersion.String()}}}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.3.0"}}`)}, - out: out{config: types.Config{Ignition: types.Ignition{Version: types.MaxVersion.String()}}}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.4.0"}}`)}, - out: out{config: types.Config{Ignition: types.Ignition{Version: types.MaxVersion.String()}}}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.5.0-experimental"}}`)}, - out: out{config: types.Config{Ignition: types.Ignition{Version: types.MaxVersion.String()}}}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.5.0"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.6.0"}}`)}, - out: out{err: errors.ErrUnknownVersion}, - }, - { - in: in{config: []byte{}}, - out: out{err: errors.ErrEmpty}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.0.0"}, "storage": {"filesystems": [{"format": "ext4", "label": "zzzzzzzzzzzzzzzzzzzzzzzzzzz"}]}}`)}, - out: out{err: errors.ErrInvalid}, - }, - { - in: in{config: []byte(`{"ignition": {"version": "3.5.0-experimental"}, "storage": {"filesystems": [{"format": "ext4", "label": "zzzzzzzzzzzzzzzzzzzzzzzzzzz"}]}}`)}, - out: out{err: errors.ErrInvalid}, - }, - } - - for i, test := range tests { - config, report, err := Parse(test.in.config) - if test.out.err != err { - t.Errorf("#%d: bad error: want %v, got %v, report: %+v", i, test.out.err, err, report) - } - if test.out.err == errors.ErrInvalid && len(report.Entries) == 0 { - t.Errorf("#%d: expected report, got none", i) - } - assert.Equal(t, test.out.config, config, "#%d: bad config, report: %+v", i, report) - } - for i, test := range testsCompt { - config, report, err := ParseCompatibleVersion(test.in.config) - if test.out.err != err { - t.Errorf("#%d: bad error: want %v, got %v, report: %+v", i, test.out.err, err, report) - } - if test.out.err == errors.ErrInvalid && len(report.Entries) == 0 { - t.Errorf("#%d: expected report, got none", i) - } - assert.Equal(t, test.out.config, config, "#%d: bad config, report: %+v", i, report) - } -} diff --git a/config/v3_5_experimental/schema/ignition.json b/config/v3_5_experimental/schema/ignition.json deleted file mode 100644 index 344d06749..000000000 --- a/config/v3_5_experimental/schema/ignition.json +++ /dev/null @@ -1,685 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "ignition", - "type": "object", - "properties": { - "ignition": { - "$ref": "#/definitions/ignition" - }, - "storage": { - "$ref": "#/definitions/storage" - }, - "systemd": { - "$ref": "#/definitions/systemd" - }, - "passwd": { - "$ref": "#/definitions/passwd" - }, - "kernelArguments": { - "$ref": "#/definitions/kernelArguments" - } - }, - "required": [ - "ignition" - ], - "definitions": { - "resource": { - "type": "object", - "properties": { - "source": { - "type": ["string", "null"] - }, - "compression": { - "type": ["string", "null"] - }, - "httpHeaders": { - "$ref": "#/definitions/httpHeaders" - }, - "verification": { - "$ref": "#/definitions/verification" - } - } - }, - "verification": { - "type": "object", - "properties": { - "hash": { "type": ["string", "null"] } - } - }, - "httpHeaders": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": ["string", "null"] - } - }, - "required": [ - "name" - ] - } - }, - "ignition": { - "type": "object", - "properties": { - "version": { - "type": "string" - }, - "config": { - "$ref": "#/definitions/ignition/definitions/ignition-config" - }, - "timeouts": { - "$ref": "#/definitions/ignition/definitions/timeouts" - }, - "security": { - "$ref": "#/definitions/ignition/definitions/security" - }, - "proxy": { - "$ref": "#/definitions/ignition/definitions/proxy" - } - }, - "definitions": { - "ignition-config": { - "type": "object", - "properties": { - "merge": { - "type": "array", - "items": { - "$ref": "#/definitions/resource" - } - }, - "replace": { - "$ref": "#/definitions/resource" - } - } - }, - "security": { - "type": "object", - "properties": { - "tls": { - "type": "object", - "properties": { - "certificateAuthorities": { - "type": "array", - "items": { - "$ref": "#/definitions/resource" - } - } - } - } - } - }, - "proxy": { - "type": "object", - "properties": { - "httpProxy": { - "type": ["string", "null"] - }, - "httpsProxy": { - "type": ["string", "null"] - }, - "noProxy": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "timeouts": { - "type": "object", - "properties": { - "httpResponseHeaders": { - "type": ["integer", "null"] - }, - "httpTotal": { - "type": ["integer", "null"] - } - } - } - }, - "required": [ - "version" - ] - }, - "storage": { - "type": "object", - "properties": { - "disks": { - "type": "array", - "items": { - "$ref": "#/definitions/storage/definitions/disk" - } - }, - "raid": { - "type": "array", - "items": { - "$ref": "#/definitions/storage/definitions/raid" - } - }, - "luks": { - "type": "array", - "items": { - "$ref": "#/definitions/storage/definitions/luks" - } - }, - "filesystems": { - "type": "array", - "items": { - "$ref": "#/definitions/storage/definitions/filesystem" - } - }, - "files": { - "type": "array", - "items": { - "$ref": "#/definitions/storage/definitions/file" - } - }, - "directories": { - "type": "array", - "items": { - "$ref": "#/definitions/storage/definitions/directory" - } - }, - "links": { - "type": "array", - "items": { - "$ref": "#/definitions/storage/definitions/link" - } - } - }, - "definitions": { - "disk": { - "type": "object", - "properties": { - "device": { - "type": "string" - }, - "wipeTable": { - "type": ["boolean", "null"] - }, - "partitions": { - "type": "array", - "items": { - "$ref": "#/definitions/storage/definitions/partition" - } - } - }, - "required": [ - "device" - ] - }, - "raid": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "level": { - "type": ["string", "null"] - }, - "spares": { - "type": ["integer", "null"] - }, - "devices": { - "type": "array", - "items": { - "type": "string" - } - }, - "options": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "name" - ] - }, - "luks": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "label": { - "type": ["string", "null"] - }, - "uuid": { - "type": ["string", "null"] - }, - "device": { - "type": ["string", "null"] - }, - "keyFile": { - "$ref": "#/definitions/resource" - }, - "wipeVolume": { - "type": ["boolean", "null"] - }, - "clevis": { - "$ref": "#/definitions/storage/definitions/clevis" - }, - "cex": { - "$ref": "#/definitions/storage/definitions/cex" - }, - "options": { - "type": "array", - "items": { - "type": "string" - } - }, - "discard": { - "type": ["boolean", "null"] - }, - "openOptions": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "name" - ] - }, - "clevis": { - "type": "object", - "properties": { - "custom": { - "$ref": "#/definitions/storage/definitions/clevisCustom" - }, - "tpm2": { - "type": ["boolean", "null"] - }, - "tang": { - "type": "array", - "items": { - "$ref": "#/definitions/storage/definitions/tang" - } - }, - "threshold": { - "type": ["integer", "null"] - } - } - }, - "clevisCustom": { - "type": "object", - "properties": { - "pin": { - "type": ["string", "null"] - }, - "config": { - "type": ["string", "null"] - }, - "needsNetwork": { - "type": ["boolean", "null"] - } - } - }, - "tang": { - "type": "object", - "properties": { - "url": { - "type": "string" - }, - "thumbprint": { - "type": ["string", "null"] - }, - "advertisement": { - "type": ["string", "null"] - } - } - }, - "cex": { - "type": "object", - "properties": { - "enabled": { - "type": ["boolean", "null"] - } - } - }, - "filesystem": { - "type": "object", - "properties": { - "path": { - "type": ["string", "null"] - }, - "device": { - "type": "string" - }, - "format": { - "type": ["string", "null"] - }, - "options": { - "type": "array", - "items": { - "type": "string" - } - }, - "mountOptions": { - "type": "array", - "items": { - "type": "string" - } - }, - "wipeFilesystem": { - "type": ["boolean", "null"] - }, - "label": { - "type": ["string", "null"] - }, - "uuid": { - "type": ["string", "null"] - } - }, - "required": [ - "device" - ] - }, - "file": { - "allOf": [ - { - "$ref": "#/definitions/storage/definitions/node" - }, - { - "type": "object", - "properties": { - "mode": { - "type": ["integer", "null"] - }, - "contents": { - "$ref": "#/definitions/resource" - }, - "append": { - "type": "array", - "items": { - "$ref": "#/definitions/resource" - } - } - } - } - ] - }, - "directory": { - "allOf": [ - { - "$ref": "#/definitions/storage/definitions/node" - }, - { - "type": "object", - "properties": { - "mode": { - "type": ["integer", "null"] - } - } - } - ] - }, - "link": { - "allOf": [ - { - "$ref": "#/definitions/storage/definitions/node" - }, - { - "type": "object", - "properties": { - "target": { - "type": ["string", "null"] - }, - "hard": { - "type": ["boolean", "null"] - } - } - } - ] - }, - "partition": { - "type": "object", - "properties": { - "label": { - "type": ["string", "null"] - }, - "number": { - "type": "integer" - }, - "sizeMiB": { - "type": ["integer", "null"] - }, - "startMiB": { - "type": ["integer", "null"] - }, - "typeGuid": { - "type": ["string", "null"] - }, - "guid": { - "type": ["string", "null"] - }, - "wipePartitionEntry": { - "type": ["boolean", "null"] - }, - "shouldExist": { - "type": ["boolean", "null"] - }, - "resize": { - "type": ["boolean", "null"] - } - } - }, - "node": { - "type": "object", - "properties": { - "path": { - "type": "string" - }, - "overwrite": { - "type": ["boolean", "null"] - }, - "user": { - "type": "object", - "properties": { - "id": { - "type": ["integer", "null"] - }, - "name": { - "type": ["string", "null"] - } - } - }, - "group": { - "type": "object", - "properties": { - "id": { - "type": ["integer", "null"] - }, - "name": { - "type": ["string", "null"] - } - } - } - }, - "required": [ - "path" - ] - } - } - }, - "systemd": { - "type": "object", - "properties": { - "units": { - "type": "array", - "items": { - "$ref": "#/definitions/systemd/definitions/unit" - } - } - }, - "definitions": { - "unit": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "enabled": { - "type": ["boolean", "null"] - }, - "mask": { - "type": ["boolean", "null"] - }, - "contents": { - "type": ["string", "null"] - }, - "dropins": { - "type": "array", - "items": { - "$ref": "#/definitions/systemd/definitions/dropin" - } - } - }, - "required": [ - "name" - ] - }, - "dropin": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "contents": { - "type": ["string", "null"] - } - }, - "required": [ - "name" - ] - } - } - }, - "kernelArguments": { - "type": "object", - "properties": { - "shouldExist": { - "type": "array", - "items": { - "$ref": "#/definitions/kernelArgument" - } - }, - "shouldNotExist": { - "type": "array", - "items": { - "$ref": "#/definitions/kernelArgument" - } - } - } - }, - "kernelArgument": { - "type": "string" - }, - "passwd": { - "type": "object", - "properties": { - "users": { - "type": "array", - "items": { - "$ref": "#/definitions/passwd/definitions/user" - } - }, - "groups": { - "type": "array", - "items": { - "$ref": "#/definitions/passwd/definitions/group" - } - } - }, - "definitions": { - "user": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "passwordHash": { - "type": ["string", "null"] - }, - "sshAuthorizedKeys": { - "type": "array", - "items": { - "type": "string" - } - }, - "uid": { - "type": ["integer", "null"] - }, - "gecos": { - "type": ["string", "null"] - }, - "homeDir": { - "type": ["string", "null"] - }, - "noCreateHome": { - "type": ["boolean", "null"] - }, - "primaryGroup": { - "type": ["string", "null"] - }, - "groups": { - "type": "array", - "items": { - "type": "string" - } - }, - "noUserGroup": { - "type": ["boolean", "null"] - }, - "system": { - "type": ["boolean", "null"] - }, - "noLogInit": { - "type": ["boolean", "null"] - }, - "shell": { - "type": ["string", "null"] - }, - "shouldExist": { - "type": ["boolean", "null"] - } - }, - "required": [ - "name" - ] - }, - "group": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "gid": { - "type": ["integer", "null"] - }, - "passwordHash": { - "type": ["string", "null"] - }, - "system": { - "type": ["boolean", "null"] - }, - "shouldExist": { - "type": ["boolean", "null"] - } - }, - "required": [ - "name" - ] - } - } - } - } -} diff --git a/config/v3_5_experimental/translate/translate.go b/config/v3_5_experimental/translate/translate.go deleted file mode 100644 index 19f6da5d1..000000000 --- a/config/v3_5_experimental/translate/translate.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package translate - -import ( - "github.com/coreos/ignition/v2/config/translate" - old_types "github.com/coreos/ignition/v2/config/v3_4/types" - "github.com/coreos/ignition/v2/config/v3_5_experimental/types" -) - -func translateIgnition(old old_types.Ignition) (ret types.Ignition) { - // use a new translator so we don't recurse infinitely - translate.NewTranslator().Translate(&old, &ret) - ret.Version = types.MaxVersion.String() - return -} - -func translateLuks(old old_types.Luks) (ret types.Luks) { - tr := translate.NewTranslator() - tr.AddCustomTranslator(translateTang) - tr.Translate(&old.Clevis, &ret.Clevis) - tr.Translate(&old.Device, &ret.Device) - tr.Translate(&old.KeyFile, &ret.KeyFile) - tr.Translate(&old.Label, &ret.Label) - tr.Translate(&old.Name, &ret.Name) - tr.Translate(&old.OpenOptions, &ret.OpenOptions) - tr.Translate(&old.Options, &ret.Options) - tr.Translate(&old.Discard, &ret.Discard) - tr.Translate(&old.UUID, &ret.UUID) - tr.Translate(&old.WipeVolume, &ret.WipeVolume) - return -} - -func translateTang(old old_types.Tang) (ret types.Tang) { - tr := translate.NewTranslator() - tr.Translate(&old.Thumbprint, &ret.Thumbprint) - tr.Translate(&old.URL, &ret.URL) - return -} - -func Translate(old old_types.Config) (ret types.Config) { - tr := translate.NewTranslator() - tr.AddCustomTranslator(translateIgnition) - tr.AddCustomTranslator(translateLuks) - tr.Translate(&old, &ret) - return -} diff --git a/config/v3_5_experimental/translate/translate_test.go b/config/v3_5_experimental/translate/translate_test.go deleted file mode 100644 index 7896facc1..000000000 --- a/config/v3_5_experimental/translate/translate_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2021 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package translate - -import ( - "reflect" - "testing" - - "github.com/coreos/ignition/v2/config/util" - old "github.com/coreos/ignition/v2/config/v3_4/types" -) - -// Check that we have valid translators for the complete config struct -// hierarchy; Translate will panic if not. We need to use a deeply non-zero -// struct to ensure translation descends into every type. -func TestTranslate(t *testing.T) { - typ := reflect.TypeOf(old.Config{}) - config := util.NonZeroValue(typ).Interface().(old.Config) - Translate(config) -} diff --git a/config/v3_5_experimental/types/cex.go b/config/v3_5_experimental/types/cex.go deleted file mode 100644 index b34f5f527..000000000 --- a/config/v3_5_experimental/types/cex.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (cm Cex) IsPresent() bool { - return util.IsTrue(cm.Enabled) -} - -func (cx Cex) Validate(c path.ContextPath) (r report.Report) { - if !util.IsTrue(cx.Enabled) { - return - } - return -} diff --git a/config/v3_5_experimental/types/cex_test.go b/config/v3_5_experimental/types/cex_test.go deleted file mode 100644 index 35d562d8f..000000000 --- a/config/v3_5_experimental/types/cex_test.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2021 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "reflect" - "testing" - - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func TestCexValidate(t *testing.T) { - tests := []struct { - in Cex - at path.ContextPath - out error - }{ - { - in: Cex{}, - out: nil, - }, - { - in: Cex{ - Enabled: util.BoolToPtr(true), - }, - out: nil, - }, - } - - for i, test := range tests { - r := test.in.Validate(path.ContextPath{}) - expected := report.Report{} - expected.AddOnError(test.at, test.out) - if !reflect.DeepEqual(expected, r) { - t.Errorf("#%d: bad report: want %v, got %v", i, expected, r) - } - } -} diff --git a/config/v3_5_experimental/types/clevis.go b/config/v3_5_experimental/types/clevis.go deleted file mode 100644 index 68887d434..000000000 --- a/config/v3_5_experimental/types/clevis.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (c Clevis) IsPresent() bool { - return util.NotEmpty(c.Custom.Pin) || - len(c.Tang) > 0 || - util.IsTrue(c.Tpm2) || - c.Threshold != nil && *c.Threshold != 0 -} - -func (cu ClevisCustom) Validate(c path.ContextPath) (r report.Report) { - if util.NilOrEmpty(cu.Pin) && util.NilOrEmpty(cu.Config) && !util.IsTrue(cu.NeedsNetwork) { - return - } - if util.NotEmpty(cu.Pin) { - switch *cu.Pin { - case "tpm2", "tang", "sss": - default: - r.AddOnError(c.Append("pin"), errors.ErrUnknownClevisPin) - } - } else { - r.AddOnError(c.Append("pin"), errors.ErrClevisPinRequired) - } - if util.NilOrEmpty(cu.Config) { - r.AddOnError(c.Append("config"), errors.ErrClevisConfigRequired) - } - return -} diff --git a/config/v3_5_experimental/types/clevis_test.go b/config/v3_5_experimental/types/clevis_test.go deleted file mode 100644 index f616868cd..000000000 --- a/config/v3_5_experimental/types/clevis_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2021 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "reflect" - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func TestClevisCustomValidate(t *testing.T) { - tests := []struct { - in ClevisCustom - at path.ContextPath - out error - }{ - { - in: ClevisCustom{}, - out: nil, - }, - { - in: ClevisCustom{ - Config: util.StrToPtr("z"), - NeedsNetwork: util.BoolToPtr(true), - Pin: util.StrToPtr("sss"), - }, - out: nil, - }, - { - in: ClevisCustom{ - Config: util.StrToPtr("z"), - }, - at: path.New("", "pin"), - out: errors.ErrClevisPinRequired, - }, - { - in: ClevisCustom{ - Config: util.StrToPtr("z"), - Pin: util.StrToPtr("z"), - }, - at: path.New("", "pin"), - out: errors.ErrUnknownClevisPin, - }, - { - in: ClevisCustom{ - Pin: util.StrToPtr("tpm2"), - }, - at: path.New("", "config"), - out: errors.ErrClevisConfigRequired, - }, - } - - for i, test := range tests { - r := test.in.Validate(path.ContextPath{}) - expected := report.Report{} - expected.AddOnError(test.at, test.out) - if !reflect.DeepEqual(expected, r) { - t.Errorf("#%d: bad report: want %v, got %v", i, expected, r) - } - } -} diff --git a/config/v3_5_experimental/types/config.go b/config/v3_5_experimental/types/config.go deleted file mode 100644 index 40c27106e..000000000 --- a/config/v3_5_experimental/types/config.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/go-semver/semver" - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -var ( - MaxVersion = semver.Version{ - Major: 3, - Minor: 5, - PreRelease: "experimental", - } -) - -func (cfg Config) Validate(c path.ContextPath) (r report.Report) { - systemdPath := "/etc/systemd/system/" - unitPaths := map[string]struct{}{} - for _, unit := range cfg.Systemd.Units { - if !util.NilOrEmpty(unit.Contents) { - pathString := systemdPath + unit.Name - unitPaths[pathString] = struct{}{} - } - for _, dropin := range unit.Dropins { - if !util.NilOrEmpty(dropin.Contents) { - pathString := systemdPath + unit.Name + ".d/" + dropin.Name - unitPaths[pathString] = struct{}{} - } - } - } - for i, f := range cfg.Storage.Files { - if _, exists := unitPaths[f.Path]; exists { - r.AddOnError(c.Append("storage", "files", i, "path"), errors.ErrPathConflictsSystemd) - } - } - for i, d := range cfg.Storage.Directories { - if _, exists := unitPaths[d.Path]; exists { - r.AddOnError(c.Append("storage", "directories", i, "path"), errors.ErrPathConflictsSystemd) - } - } - for i, l := range cfg.Storage.Links { - if _, exists := unitPaths[l.Path]; exists { - r.AddOnError(c.Append("storage", "links", i, "path"), errors.ErrPathConflictsSystemd) - } - } - return -} diff --git a/config/v3_5_experimental/types/config_test.go b/config/v3_5_experimental/types/config_test.go deleted file mode 100644 index 3d82627b2..000000000 --- a/config/v3_5_experimental/types/config_test.go +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "reflect" - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func TestConfigValidation(t *testing.T) { - tests := []struct { - in Config - out error - at path.ContextPath - }{ - // test 0: file conflicts with systemd dropin file, error - { - in: Config{ - Storage: Storage{ - Files: []File{ - { - Node: Node{Path: "/etc/systemd/system/foo.service.d/bar.conf"}, - }, - }, - }, - Systemd: Systemd{ - Units: []Unit{ - { - Name: "foo.service", - Dropins: []Dropin{ - { - Name: "bar.conf", - Contents: util.StrToPtr("[Foo]\nQux=Bar"), - }, - }, - }, - }, - }, - }, - out: errors.ErrPathConflictsSystemd, - at: path.New("json", "storage", "files", 0, "path"), - }, - // test 1: file conflicts with systemd unit, error - { - in: Config{ - Storage: Storage{ - Files: []File{ - { - Node: Node{Path: "/etc/systemd/system/foo.service"}, - }, - }, - }, - Systemd: Systemd{ - Units: []Unit{ - { - Name: "foo.service", - Contents: util.StrToPtr("[Foo]\nQux=Bar"), - Enabled: util.BoolToPtr(true), - }, - }, - }, - }, - out: errors.ErrPathConflictsSystemd, - at: path.New("json", "storage", "files", 0, "path"), - }, - // test 2: directory conflicts with systemd dropin file, error - { - in: Config{ - Storage: Storage{ - Directories: []Directory{ - { - Node: Node{Path: "/etc/systemd/system/foo.service.d/bar.conf"}, - }, - }, - }, - Systemd: Systemd{ - []Unit{ - { - Name: "foo.service", - Dropins: []Dropin{ - { - Name: "bar.conf", - Contents: util.StrToPtr("[Foo]\nQux=Bar"), - }, - }, - }, - }, - }, - }, - out: errors.ErrPathConflictsSystemd, - at: path.New("json", "storage", "directories", 0, "path"), - }, - // test 3: directory conflicts with systemd unit, error - { - in: Config{ - Storage: Storage{ - Directories: []Directory{ - { - Node: Node{Path: "/etc/systemd/system/foo.service"}, - }, - }, - }, - Systemd: Systemd{ - []Unit{ - { - Name: "foo.service", - Contents: util.StrToPtr("[foo]\nQux=Baz"), - Enabled: util.BoolToPtr(true), - }, - }, - }, - }, - out: errors.ErrPathConflictsSystemd, - at: path.New("json", "storage", "directories", 0, "path"), - }, - // test 4: link conflicts with systemd dropin file, error - { - in: Config{ - Storage: Storage{ - Links: []Link{ - { - Node: Node{Path: "/etc/systemd/system/foo.service.d/bar.conf"}, - LinkEmbedded1: LinkEmbedded1{Target: util.StrToPtr("/qux.conf")}, - }, - }, - }, - Systemd: Systemd{ - []Unit{ - { - Name: "foo.service", - Dropins: []Dropin{ - { - Name: "bar.conf", - Contents: util.StrToPtr("[Foo]\nQux=Bar"), - }, - }, - }, - }, - }, - }, - out: errors.ErrPathConflictsSystemd, - at: path.New("json", "storage", "links", 0, "path"), - }, - // test 5: link conflicts with systemd unit, error - { - in: Config{ - Storage: Storage{ - Links: []Link{ - { - Node: Node{Path: "/etc/systemd/system/foo.service"}, - LinkEmbedded1: LinkEmbedded1{Target: util.StrToPtr("/qux.conf")}, - }, - }, - }, - Systemd: Systemd{ - []Unit{ - { - Name: "foo.service", - Contents: util.StrToPtr("[foo]\nQux=Baz"), - Enabled: util.BoolToPtr(true), - }, - }, - }, - }, - out: errors.ErrPathConflictsSystemd, - at: path.New("json", "storage", "links", 0, "path"), - }, - // test 6: non-conflicting scenarios - { - in: Config{ - Storage: Storage{ - Files: []File{ - { - Node: Node{Path: "/etc/systemd/system/bar.service.d/baz.conf"}, - }, - { - Node: Node{Path: "/etc/systemd/system/bar.service"}, - }, - { - Node: Node{Path: "/etc/systemd/system/foo.service.d/qux.conf"}, - }, - }, - Links: []Link{ - { - Node: Node{Path: "/etc/systemd/system/qux.service"}, - LinkEmbedded1: LinkEmbedded1{Target: util.StrToPtr("/qux.conf")}, - }, - { - Node: Node{Path: "/etc/systemd/system/quux.service.d/foo.conf"}, - LinkEmbedded1: LinkEmbedded1{Target: util.StrToPtr("/foo.conf")}, - }, - }, - Directories: []Directory{ - { - Node: Node{Path: "/etc/systemd/system/quux.service.d"}, - }, - }, - }, - Systemd: Systemd{ - Units: []Unit{ - { - Name: "foo.service", - Contents: util.StrToPtr("[Foo]\nQux=Baz"), - Enabled: util.BoolToPtr(true), - }, - { - Name: "bar.service", - Dropins: []Dropin{ - { - Name: "baz.conf", - }, - }, - Enabled: util.BoolToPtr(true), - }, - { - Name: "qux.service", - Dropins: []Dropin{ - { - Name: "bar.conf", - Contents: util.StrToPtr("[Foo]\nQux=Baz"), - }, - }, - }, - { - Name: "quux.service", - Contents: util.StrToPtr("[Foo]\nQux=Baz"), - Enabled: util.BoolToPtr(true), - }, - }, - }, - }, - }, - } - for i, test := range tests { - r := test.in.Validate(path.New("json")) - expected := report.Report{} - expected.AddOnError(test.at, test.out) - if !reflect.DeepEqual(expected, r) { - t.Errorf("#%d: bad error: expected : %v, got %v", i, expected, r) - } - } -} diff --git a/config/v3_5_experimental/types/device.go b/config/v3_5_experimental/types/device.go deleted file mode 100644 index a10ce97b0..000000000 --- a/config/v3_5_experimental/types/device.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (d Device) Validate(c path.ContextPath) (r report.Report) { - r.AddOnError(c, validatePath(string(d))) - return -} diff --git a/config/v3_5_experimental/types/directory.go b/config/v3_5_experimental/types/directory.go deleted file mode 100644 index f6f068455..000000000 --- a/config/v3_5_experimental/types/directory.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (d Directory) Validate(c path.ContextPath) (r report.Report) { - r.Merge(d.Node.Validate(c)) - r.AddOnError(c.Append("mode"), validateMode(d.Mode)) - return -} diff --git a/config/v3_5_experimental/types/disk.go b/config/v3_5_experimental/types/disk.go deleted file mode 100644 index 8caf8499d..000000000 --- a/config/v3_5_experimental/types/disk.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (d Disk) Key() string { - return d.Device -} - -func (n Disk) Validate(c path.ContextPath) (r report.Report) { - if len(n.Device) == 0 { - r.AddOnError(c.Append("device"), errors.ErrDiskDeviceRequired) - return - } - r.AddOnError(c.Append("device"), validatePath(n.Device)) - - if collides, p := n.partitionNumbersCollide(); collides { - r.AddOnError(c.Append("partitions", p), errors.ErrPartitionNumbersCollide) - } - if overlaps, p := n.partitionsOverlap(); overlaps { - r.AddOnError(c.Append("partitions", p), errors.ErrPartitionsOverlap) - } - if n.partitionsMixZeroesAndNonexistence() { - r.AddOnError(c.Append("partitions"), errors.ErrZeroesWithShouldNotExist) - } - if collides, p := n.partitionLabelsCollide(); collides { - r.AddOnError(c.Append("partitions", p), errors.ErrDuplicateLabels) - } - return -} - -// partitionNumbersCollide returns true if partition numbers in n.Partitions are not unique. It also returns the -// index of the colliding partition -func (n Disk) partitionNumbersCollide() (bool, int) { - m := map[int][]int{} // from partition number to index into array - for i, p := range n.Partitions { - if p.Number != 0 { - // a number of 0 means next available number, multiple devices can specify this - m[p.Number] = append(m[p.Number], i) - } - } - for _, n := range m { - if len(n) > 1 { - // TODO(vc): return information describing the collision for logging - return true, n[1] - } - } - return false, 0 -} - -func (d Disk) partitionLabelsCollide() (bool, int) { - m := map[string]struct{}{} - for i, p := range d.Partitions { - if p.Label != nil { - // a number of 0 means next available number, multiple devices can specify this - if _, exists := m[*p.Label]; exists { - return true, i - } - m[*p.Label] = struct{}{} - } - } - return false, 0 -} - -// end returns the last sector of a partition. Only used by partitionsOverlap. Requires non-nil Start and Size. -func (p Partition) end() int { - if *p.SizeMiB == 0 { - // a size of 0 means "fill available", just return the start as the end for those. - return *p.StartMiB - } - return *p.StartMiB + *p.SizeMiB - 1 -} - -// partitionsOverlap returns true if any explicitly dimensioned partitions overlap. It also returns the index of -// the overlapping partition -func (n Disk) partitionsOverlap() (bool, int) { - for _, p := range n.Partitions { - // Starts of 0 are placed by sgdisk into the "largest available block" at that time. - // We aren't going to check those for overlap since we don't have the disk geometry. - if p.StartMiB == nil || p.SizeMiB == nil || *p.StartMiB == 0 { - continue - } - - for i, o := range n.Partitions { - if o.StartMiB == nil || o.SizeMiB == nil || p == o || *o.StartMiB == 0 { - continue - } - - // is p.StartMiB within o? - if *p.StartMiB >= *o.StartMiB && *p.StartMiB <= o.end() { - return true, i - } - - // is p.end() within o? - if p.end() >= *o.StartMiB && p.end() <= o.end() { - return true, i - } - - // do p.StartMiB and p.end() straddle o? - if *p.StartMiB < *o.StartMiB && p.end() > o.end() { - return true, i - } - } - } - return false, 0 -} - -func (n Disk) partitionsMixZeroesAndNonexistence() bool { - hasZero := false - hasShouldNotExist := false - for _, p := range n.Partitions { - hasShouldNotExist = hasShouldNotExist || util.IsFalse(p.ShouldExist) - hasZero = hasZero || (p.Number == 0) - } - return hasZero && hasShouldNotExist -} diff --git a/config/v3_5_experimental/types/file.go b/config/v3_5_experimental/types/file.go deleted file mode 100644 index 9b71bb26a..000000000 --- a/config/v3_5_experimental/types/file.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (f File) Validate(c path.ContextPath) (r report.Report) { - r.Merge(f.Node.Validate(c)) - r.AddOnError(c.Append("mode"), validateMode(f.Mode)) - r.AddOnError(c.Append("overwrite"), f.validateOverwrite()) - return -} - -func (f File) validateOverwrite() error { - if util.IsTrue(f.Overwrite) && f.Contents.Source == nil { - return errors.ErrOverwriteAndNilSource - } - return nil -} - -func (f FileEmbedded1) IgnoreDuplicates() map[string]struct{} { - return map[string]struct{}{ - "Append": {}, - } -} diff --git a/config/v3_5_experimental/types/file_test.go b/config/v3_5_experimental/types/file_test.go deleted file mode 100644 index 449e07009..000000000 --- a/config/v3_5_experimental/types/file_test.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" -) - -func TestFileValidateOverwrite(t *testing.T) { - tests := []struct { - in File - out error - }{ - { - File{}, - nil, - }, - { - File{ - Node: Node{ - Overwrite: util.BoolToPtr(true), - }, - }, - errors.ErrOverwriteAndNilSource, - }, - { - File{ - Node: Node{ - Overwrite: util.BoolToPtr(true), - }, - FileEmbedded1: FileEmbedded1{ - Contents: Resource{ - Source: util.StrToPtr(""), - }, - }, - }, - nil, - }, - { - File{ - Node: Node{ - Overwrite: util.BoolToPtr(true), - }, - FileEmbedded1: FileEmbedded1{ - Contents: Resource{ - Source: util.StrToPtr("http://example.com"), - }, - }, - }, - nil, - }, - } - - for i, test := range tests { - err := test.in.validateOverwrite() - if test.out != err { - t.Errorf("#%d: bad error: want %v, got %v", i, test.out, err) - } - } -} - -func TestFileContentsValidate(t *testing.T) { - tests := []struct { - in Resource - out error - }{ - { - Resource{}, - nil, - }, - { - Resource{ - Source: util.StrToPtr(""), - }, - nil, - }, - { - Resource{ - Source: util.StrToPtr(""), - Verification: Verification{ - Hash: util.StrToPtr(""), - }, - }, - nil, - }, - { - Resource{ - Verification: Verification{ - Hash: util.StrToPtr(""), - }, - }, - errors.ErrVerificationAndNilSource, - }, - } - - for i, test := range tests { - err := test.in.validateVerification() - if test.out != err { - t.Errorf("#%d: bad error: want %v, got %v", i, test.out, err) - } - } -} diff --git a/config/v3_5_experimental/types/filesystem.go b/config/v3_5_experimental/types/filesystem.go deleted file mode 100644 index c722b3633..000000000 --- a/config/v3_5_experimental/types/filesystem.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (f Filesystem) Key() string { - return f.Device -} - -func (f Filesystem) IgnoreDuplicates() map[string]struct{} { - return map[string]struct{}{ - "Options": {}, - "MountOptions": {}, - } -} - -func (f Filesystem) Validate(c path.ContextPath) (r report.Report) { - r.AddOnError(c.Append("path"), f.validatePath()) - r.AddOnError(c.Append("device"), validatePath(f.Device)) - r.AddOnError(c.Append("format"), f.validateFormat()) - r.AddOnError(c.Append("label"), f.validateLabel()) - return -} - -func (f Filesystem) validatePath() error { - return validatePathNilOK(f.Path) -} - -func (f Filesystem) validateFormat() error { - if util.NilOrEmpty(f.Format) { - if util.NotEmpty(f.Path) || - util.NotEmpty(f.Label) || - util.NotEmpty(f.UUID) || - util.IsTrue(f.WipeFilesystem) || - len(f.MountOptions) != 0 || - len(f.Options) != 0 { - return errors.ErrFormatNilWithOthers - } - } else { - switch *f.Format { - case "ext4", "btrfs", "xfs", "swap", "vfat", "none": - default: - return errors.ErrFilesystemInvalidFormat - } - } - return nil -} - -func (f Filesystem) validateLabel() error { - if util.NilOrEmpty(f.Label) { - return nil - } - if util.NilOrEmpty(f.Format) { - return errors.ErrLabelNeedsFormat - } - - switch *f.Format { - case "ext4": - if len(*f.Label) > 16 { - // source: man mkfs.ext4 - return errors.ErrExt4LabelTooLong - } - case "btrfs": - if len(*f.Label) > 256 { - // source: man mkfs.btrfs - return errors.ErrBtrfsLabelTooLong - } - case "xfs": - if len(*f.Label) > 12 { - // source: man mkfs.xfs - return errors.ErrXfsLabelTooLong - } - case "swap": - // mkswap's man page does not state a limit on label size, but through - // experimentation it appears that mkswap will truncate long labels to - // 15 characters, so let's enforce that. - if len(*f.Label) > 15 { - return errors.ErrSwapLabelTooLong - } - case "vfat": - if len(*f.Label) > 11 { - // source: man mkfs.fat - return errors.ErrVfatLabelTooLong - } - } - return nil -} diff --git a/config/v3_5_experimental/types/filesystem_test.go b/config/v3_5_experimental/types/filesystem_test.go deleted file mode 100644 index 1f8db9037..000000000 --- a/config/v3_5_experimental/types/filesystem_test.go +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" -) - -func TestFilesystemValidateFormat(t *testing.T) { - tests := []struct { - in Filesystem - out error - }{ - { - Filesystem{Format: util.StrToPtr("ext4")}, - nil, - }, - { - Filesystem{Format: util.StrToPtr("btrfs")}, - nil, - }, - { - Filesystem{Format: util.StrToPtr("")}, - nil, - }, - { - Filesystem{Format: nil}, - nil, - }, - { - Filesystem{Label: util.StrToPtr("z")}, - errors.ErrFormatNilWithOthers, - }, - { - Filesystem{MountOptions: []MountOption{MountOption("z")}}, - errors.ErrFormatNilWithOthers, - }, - { - Filesystem{Options: []FilesystemOption{FilesystemOption("z")}}, - errors.ErrFormatNilWithOthers, - }, - { - Filesystem{Format: util.StrToPtr(""), Path: util.StrToPtr("/")}, - errors.ErrFormatNilWithOthers, - }, - { - Filesystem{Format: nil, Path: util.StrToPtr("/")}, - errors.ErrFormatNilWithOthers, - }, - { - Filesystem{UUID: util.StrToPtr("z")}, - errors.ErrFormatNilWithOthers, - }, - { - Filesystem{WipeFilesystem: util.BoolToPtr(true)}, - errors.ErrFormatNilWithOthers, - }, - } - - for i, test := range tests { - err := test.in.validateFormat() - if test.out != err { - t.Errorf("#%d: bad error: want %v, got %v", i, test.out, err) - } - } -} - -func TestFilesystemValidatePath(t *testing.T) { - tests := []struct { - in Filesystem - out error - }{ - { - Filesystem{Path: util.StrToPtr("/foo")}, - nil, - }, - { - Filesystem{Path: util.StrToPtr("")}, - nil, - }, - { - Filesystem{Path: nil}, - nil, - }, - { - Filesystem{Path: util.StrToPtr("foo")}, - errors.ErrPathRelative, - }, - } - - for i, test := range tests { - err := test.in.validatePath() - if test.out != err { - t.Errorf("#%d: bad error: want %v, got %v", i, test.out, err) - } - } -} - -func TestLabelValidate(t *testing.T) { - type in struct { - filesystem Filesystem - } - type out struct { - err error - } - - tests := []struct { - in in - out out - }{ - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("ext4"), Label: nil}}, - out: out{}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("ext4"), Label: util.StrToPtr("data")}}, - out: out{}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("ext4"), Label: util.StrToPtr("thislabelistoolong")}}, - out: out{err: errors.ErrExt4LabelTooLong}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("btrfs"), Label: nil}}, - out: out{}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("btrfs"), Label: util.StrToPtr("thislabelisnottoolong")}}, - out: out{}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("btrfs"), Label: util.StrToPtr("thislabelistoolongthislabelistoolongthislabelistoolongthislabelistoolongthislabelistoolongthislabelistoolongthislabelistoolongthislabelistoolongthislabelistoolongthislabelistoolongthislabelistoolongthislabelistoolongthislabelistoolongthislabelistoolongthislabelistoolong")}}, - out: out{err: errors.ErrBtrfsLabelTooLong}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("xfs"), Label: nil}}, - out: out{}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("xfs"), Label: util.StrToPtr("data")}}, - out: out{}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("xfs"), Label: util.StrToPtr("thislabelistoolong")}}, - out: out{err: errors.ErrXfsLabelTooLong}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("swap"), Label: nil}}, - out: out{}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("swap"), Label: util.StrToPtr("data")}}, - out: out{}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("swap"), Label: util.StrToPtr("thislabelistoolong")}}, - out: out{err: errors.ErrSwapLabelTooLong}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("vfat"), Label: nil}}, - out: out{}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("vfat"), Label: util.StrToPtr("data")}}, - out: out{}, - }, - { - in: in{filesystem: Filesystem{Format: util.StrToPtr("vfat"), Label: util.StrToPtr("thislabelistoolong")}}, - out: out{err: errors.ErrVfatLabelTooLong}, - }, - } - - for i, test := range tests { - err := test.in.filesystem.validateLabel() - if test.out.err != err { - t.Errorf("#%d: bad error: want %v, got %v", i, test.out.err, err) - } - } -} diff --git a/config/v3_5_experimental/types/headers.go b/config/v3_5_experimental/types/headers.go deleted file mode 100644 index be1aadad9..000000000 --- a/config/v3_5_experimental/types/headers.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "net/http" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -// Parse generates standard net/http headers from the data in HTTPHeaders -func (hs HTTPHeaders) Parse() (http.Header, error) { - headers := http.Header{} - for _, header := range hs { - if header.Name == "" { - return nil, errors.ErrEmptyHTTPHeaderName - } - if header.Value == nil || string(*header.Value) == "" { - return nil, errors.ErrInvalidHTTPHeader - } - headers.Add(header.Name, string(*header.Value)) - } - return headers, nil -} - -func (h HTTPHeader) Validate(c path.ContextPath) (r report.Report) { - r.AddOnError(c.Append("name"), h.validateName()) - r.AddOnError(c.Append("value"), h.validateValue()) - return -} - -func (h HTTPHeader) validateName() error { - if h.Name == "" { - return errors.ErrEmptyHTTPHeaderName - } - return nil -} - -func (h HTTPHeader) validateValue() error { - if h.Value == nil { - return nil - } - if string(*h.Value) == "" { - return errors.ErrInvalidHTTPHeader - } - return nil -} - -func (h HTTPHeader) Key() string { - return h.Name -} diff --git a/config/v3_5_experimental/types/headers_test.go b/config/v3_5_experimental/types/headers_test.go deleted file mode 100644 index 40380b684..000000000 --- a/config/v3_5_experimental/types/headers_test.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" -) - -func toPointer(val string) *string { - return &val -} - -func equal(a, b []string) bool { - if len(a) != len(b) { - return false - } - for i, v := range a { - if v != b[i] { - return false - } - } - return true -} - -func TestHeadersParse(t *testing.T) { - tests := []struct { - in HTTPHeaders - out error - }{ - { - // Valid headers - HTTPHeaders{ - HTTPHeader{ - Name: "header1", - Value: toPointer("header1value"), - }, - HTTPHeader{ - Name: "header2", - Value: toPointer("header2value"), - }, - }, - nil, - }, - { - // Duplicate headers - HTTPHeaders{ - HTTPHeader{ - Name: "header1", - Value: toPointer("header1value"), - }, - HTTPHeader{ - Name: "header1", - Value: toPointer("header2value"), - }, - }, - nil, - }, - { - // No header name - HTTPHeaders{ - HTTPHeader{ - Name: "header1", - Value: toPointer("header1value"), - }, - HTTPHeader{ - Value: toPointer("emptyheadervalue"), - }, - }, - errors.ErrEmptyHTTPHeaderName, - }, - { - // No header value - HTTPHeaders{ - HTTPHeader{ - Name: "header1", - Value: toPointer("header1value"), - }, - HTTPHeader{ - Name: "emptyheadername", - }, - }, - errors.ErrInvalidHTTPHeader, - }, - { - // Invalid header without elements - HTTPHeaders{ - HTTPHeader{ - Name: "header1", - Value: toPointer("header1value"), - }, - HTTPHeader{}, - }, - errors.ErrEmptyHTTPHeaderName, - }, - } - - for i, test := range tests { - _, err := test.in.Parse() - if test.out != err { - t.Errorf("#%d: bad error: want %v, got %v", i, test.out, err) - } - } -} - -func TestValidHeadersParse(t *testing.T) { - // Valid headers - headers := HTTPHeaders{ - HTTPHeader{ - Name: "header1", - Value: toPointer("header1value"), - }, - HTTPHeader{ - Name: "header2", - Value: toPointer("header2value"), - }, - } - parseHeaders, err := headers.Parse() - if err != nil { - t.Errorf("error during parsing valid headers: %v", err) - } - if !equal(parseHeaders["Header1"], []string{"header1value"}) || !equal(parseHeaders["Header2"], []string{"header2value"}) { - t.Errorf("parsed HTTP headers values are wrong") - } -} - -func TestDuplicateHeadersParse(t *testing.T) { - // Duplicate headers - headers := HTTPHeaders{ - HTTPHeader{ - Name: "header1", - Value: toPointer("header1value"), - }, - HTTPHeader{ - Name: "header1", - Value: toPointer("header2value"), - }, - } - parseHeaders, err := headers.Parse() - if err != nil { - t.Errorf("error during parsing valid headers: %v", err) - } - if !equal(parseHeaders["Header1"], []string{"header1value", "header2value"}) { - t.Errorf("parsed HTTP headers values are wrong") - } -} diff --git a/config/v3_5_experimental/types/ignition.go b/config/v3_5_experimental/types/ignition.go deleted file mode 100644 index 190445bda..000000000 --- a/config/v3_5_experimental/types/ignition.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "github.com/coreos/go-semver/semver" - - "github.com/coreos/ignition/v2/config/shared/errors" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (v Ignition) Semver() (*semver.Version, error) { - return semver.NewVersion(v.Version) -} - -func (ic IgnitionConfig) Validate(c path.ContextPath) (r report.Report) { - for i, res := range ic.Merge { - r.AddOnError(c.Append("merge", i), res.validateRequiredSource()) - } - return -} - -func (v Ignition) Validate(c path.ContextPath) (r report.Report) { - c = c.Append("version") - tv, err := v.Semver() - if err != nil { - r.AddOnError(c, errors.ErrInvalidVersion) - return - } - - if MaxVersion != *tv { - r.AddOnError(c, errors.ErrUnknownVersion) - } - return -} diff --git a/config/v3_5_experimental/types/ignition_test.go b/config/v3_5_experimental/types/ignition_test.go deleted file mode 100644 index ac7d462d3..000000000 --- a/config/v3_5_experimental/types/ignition_test.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "testing" - - "github.com/coreos/vcontext/validate" -) - -func TestIgnitionConfigValidate(t *testing.T) { - tests := []struct { - in IgnitionConfig - out string - }{ - { - IgnitionConfig{ - Merge: []Resource{{}}, - }, - "error at $.merge.0: source is required\n", - }, - { - IgnitionConfig{ - Replace: Resource{}, - }, - "", - }, - } - - for i, test := range tests { - r := validate.Validate(test.in, "test") - if test.out != r.String() { - t.Errorf("#%d: bad error: want %q, got %q", i, test.out, r.String()) - } - } -} diff --git a/config/v3_5_experimental/types/kargs.go b/config/v3_5_experimental/types/kargs.go deleted file mode 100644 index 42c29408e..000000000 --- a/config/v3_5_experimental/types/kargs.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2021 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -func (k KernelArguments) MergedKeys() map[string]string { - return map[string]string{ - "ShouldExist": "KernelArgument", - "ShouldNotExist": "KernelArgument", - } -} diff --git a/config/v3_5_experimental/types/kargs_test.go b/config/v3_5_experimental/types/kargs_test.go deleted file mode 100644 index 1a258727e..000000000 --- a/config/v3_5_experimental/types/kargs_test.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2021 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "testing" - - "github.com/coreos/ignition/v2/config/validate" -) - -func TestKernelArgumentsValidate(t *testing.T) { - tests := []struct { - in KernelArguments - out string - }{ - // Ensure that ValidateWithContext prevents duplicate entries - // in ShouldExist & ShouldNotExist - { - KernelArguments{ - ShouldExist: []KernelArgument{ - "foo", - "bar", - }, - ShouldNotExist: []KernelArgument{ - "baz", - "foo", - }, - }, - "error at $.shouldNotExist.1: duplicate entry defined\n", - }, - } - - for i, test := range tests { - r := validate.ValidateWithContext(test.in, nil) - if test.out != r.String() { - t.Errorf("#%d: bad error: want %q, got %q", i, test.out, r.String()) - } - } -} diff --git a/config/v3_5_experimental/types/luks.go b/config/v3_5_experimental/types/luks.go deleted file mode 100644 index e4c1d6815..000000000 --- a/config/v3_5_experimental/types/luks.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "strings" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (l Luks) Key() string { - return l.Name -} - -func (l Luks) IgnoreDuplicates() map[string]struct{} { - return map[string]struct{}{ - "Options": {}, - } -} - -func (l Luks) Validate(c path.ContextPath) (r report.Report) { - if strings.Contains(l.Name, "/") { - r.AddOnError(c.Append("name"), errors.ErrLuksNameContainsSlash) - } - r.AddOnError(c.Append("label"), l.validateLabel()) - if util.NilOrEmpty(l.Device) { - r.AddOnError(c.Append("device"), errors.ErrDiskDeviceRequired) - } else { - r.AddOnError(c.Append("device"), validatePath(*l.Device)) - } - - if util.NotEmpty(l.Clevis.Custom.Pin) && (len(l.Clevis.Tang) > 0 || util.IsTrue(l.Clevis.Tpm2) || (l.Clevis.Threshold != nil && *l.Clevis.Threshold != 0)) { - r.AddOnError(c.Append("clevis"), errors.ErrClevisCustomWithOthers) - } - - // fail if a key file is provided and is not valid - if err := validateURLNilOK(l.KeyFile.Source); err != nil { - r.AddOnError(c.Append("keys"), errors.ErrInvalidLuksKeyFile) - } - - // fail if Cex use with Clevis - if l.Clevis.IsPresent() && l.Cex.IsPresent() { - r.AddOnError(c.Append("cex"), errors.ErrCexWithClevis) - } - - // fail if key file is provided along with Cex - if l.Cex.IsPresent() && util.NotEmpty(l.KeyFile.Source) { - r.AddOnError(c.Append("cex"), errors.ErrCexWithKeyFile) - } - - return -} - -func (l Luks) validateLabel() error { - if util.NilOrEmpty(l.Label) { - return nil - } - - if len(*l.Label) > 47 { - // LUKS2_LABEL_L has a maximum length of 48 (including the null terminator) - // https://gitlab.com/cryptsetup/cryptsetup/-/blob/1633f030e89ad2f11ae649ba9600997a41abd3fc/lib/luks2/luks2.h#L86 - return errors.ErrLuksLabelTooLong - } - - return nil -} diff --git a/config/v3_5_experimental/types/mode.go b/config/v3_5_experimental/types/mode.go deleted file mode 100644 index 9eb7573d8..000000000 --- a/config/v3_5_experimental/types/mode.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "github.com/coreos/ignition/v2/config/shared/errors" -) - -func validateMode(m *int) error { - if m != nil && (*m < 0 || *m > 07777) { - return errors.ErrFileIllegalMode - } - return nil -} diff --git a/config/v3_5_experimental/types/mode_test.go b/config/v3_5_experimental/types/mode_test.go deleted file mode 100644 index 8966e25d8..000000000 --- a/config/v3_5_experimental/types/mode_test.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "reflect" - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" -) - -func TestModeValidate(t *testing.T) { - tests := []struct { - in *int - out error - }{ - { - nil, - nil, - }, - { - util.IntToPtr(0), - nil, - }, - { - util.IntToPtr(0644), - nil, - }, - { - util.IntToPtr(01755), - nil, - }, - { - util.IntToPtr(07777), - nil, - }, - { - util.IntToPtr(010000), - errors.ErrFileIllegalMode, - }, - } - - for i, test := range tests { - err := validateMode(test.in) - if !reflect.DeepEqual(test.out, err) { - t.Errorf("#%d: bad err: want %v, got %v", i, test.out, err) - } - } -} diff --git a/config/v3_5_experimental/types/node.go b/config/v3_5_experimental/types/node.go deleted file mode 100644 index 248276e73..000000000 --- a/config/v3_5_experimental/types/node.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "path" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - vpath "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (n Node) Key() string { - return n.Path -} - -func (n Node) Validate(c vpath.ContextPath) (r report.Report) { - r.AddOnError(c.Append("path"), validatePath(n.Path)) - return -} - -func (n Node) Depth() int { - count := 0 - for p := path.Clean(string(n.Path)); p != "/"; count++ { - p = path.Dir(p) - } - return count -} - -func validateIDorName(id *int, name *string) error { - if id != nil && util.NotEmpty(name) { - return errors.ErrBothIDAndNameSet - } - return nil -} - -func (nu NodeUser) Validate(c vpath.ContextPath) (r report.Report) { - r.AddOnError(c, validateIDorName(nu.ID, nu.Name)) - return -} - -func (ng NodeGroup) Validate(c vpath.ContextPath) (r report.Report) { - r.AddOnError(c, validateIDorName(ng.ID, ng.Name)) - return -} diff --git a/config/v3_5_experimental/types/node_test.go b/config/v3_5_experimental/types/node_test.go deleted file mode 100644 index 20ba4eb67..000000000 --- a/config/v3_5_experimental/types/node_test.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "reflect" - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func TestNodeValidatePath(t *testing.T) { - node := Node{Path: "not/absolute"} - rep := report.Report{} - rep.AddOnError(path.ContextPath{}.Append("path"), errors.ErrPathRelative) - if receivedRep := node.Validate(path.ContextPath{}); !reflect.DeepEqual(rep, receivedRep) { - t.Errorf("bad error: want %v, got %v", rep, receivedRep) - } -} - -func TestNodeValidateUser(t *testing.T) { - tests := []struct { - in NodeUser - out error - }{ - { - NodeUser{util.IntToPtr(0), util.StrToPtr("")}, - nil, - }, - { - NodeUser{util.IntToPtr(1000), util.StrToPtr("")}, - nil, - }, - { - NodeUser{nil, util.StrToPtr("core")}, - nil, - }, - { - NodeUser{util.IntToPtr(1000), util.StrToPtr("core")}, - errors.ErrBothIDAndNameSet, - }, - } - - for i, test := range tests { - r := test.in.Validate(path.ContextPath{}) - expected := report.Report{} - expected.AddOnError(path.New(""), test.out) - if !reflect.DeepEqual(expected, r) { - t.Errorf("#%d: bad report: want %v got %v", i, test.out, r) - } - } -} - -func TestNodeValidateGroup(t *testing.T) { - tests := []struct { - in NodeGroup - out error - }{ - { - NodeGroup{util.IntToPtr(0), util.StrToPtr("")}, - nil, - }, - { - NodeGroup{util.IntToPtr(1000), util.StrToPtr("")}, - nil, - }, - { - NodeGroup{nil, util.StrToPtr("core")}, - nil, - }, - { - NodeGroup{util.IntToPtr(1000), util.StrToPtr("core")}, - errors.ErrBothIDAndNameSet, - }, - } - - for i, test := range tests { - r := test.in.Validate(path.ContextPath{}) - expected := report.Report{} - expected.AddOnError(path.New(""), test.out) - if !reflect.DeepEqual(expected, r) { - t.Errorf("#%d: bad report: want %v got %v", i, test.out, r) - } - } -} diff --git a/config/v3_5_experimental/types/partition.go b/config/v3_5_experimental/types/partition.go deleted file mode 100644 index 1b2d97edf..000000000 --- a/config/v3_5_experimental/types/partition.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "fmt" - "regexp" - "strings" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -const ( - guidRegexStr = "^(|[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12})$" -) - -var ( - guidRegex = regexp.MustCompile(guidRegexStr) -) - -func (p Partition) Key() string { - if p.Number != 0 { - return fmt.Sprintf("number:%d", p.Number) - } else if p.Label != nil { - return fmt.Sprintf("label:%s", *p.Label) - } else { - return "" - } -} - -func (p Partition) Validate(c path.ContextPath) (r report.Report) { - if util.IsFalse(p.ShouldExist) && - (p.Label != nil || util.NotEmpty(p.TypeGUID) || util.NotEmpty(p.GUID) || p.StartMiB != nil || p.SizeMiB != nil) { - r.AddOnError(c, errors.ErrShouldNotExistWithOthers) - } - if p.Number == 0 && p.Label == nil { - r.AddOnError(c, errors.ErrNeedLabelOrNumber) - } - - r.AddOnError(c.Append("label"), p.validateLabel()) - r.AddOnError(c.Append("guid"), validateGUID(p.GUID)) - r.AddOnError(c.Append("typeGuid"), validateGUID(p.TypeGUID)) - return -} - -func (p Partition) validateLabel() error { - if p.Label == nil { - return nil - } - // http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_entries: - // 56 (0x38) 72 bytes Partition name (36 UTF-16LE code units) - - // XXX(vc): note GPT calls it a name, we're using label for consistency - // with udev naming /dev/disk/by-partlabel/*. - if len(*p.Label) > 36 { - return errors.ErrLabelTooLong - } - - // sgdisk uses colons for delimitting compound arguments and does not allow escaping them. - if strings.Contains(*p.Label, ":") { - return errors.ErrLabelContainsColon - } - return nil -} - -func validateGUID(guidPointer *string) error { - if guidPointer == nil { - return nil - } - guid := *guidPointer - if ok := guidRegex.MatchString(guid); !ok { - return errors.ErrDoesntMatchGUIDRegex - } - return nil -} diff --git a/config/v3_5_experimental/types/partition_test.go b/config/v3_5_experimental/types/partition_test.go deleted file mode 100644 index a1e1623f4..000000000 --- a/config/v3_5_experimental/types/partition_test.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" -) - -func TestValidateLabel(t *testing.T) { - tests := []struct { - in *string - out error - }{ - { - util.StrToPtr("root"), - nil, - }, - { - util.StrToPtr(""), - nil, - }, - { - nil, - nil, - }, - { - util.StrToPtr("111111111111111111111111111111111111"), - nil, - }, - { - util.StrToPtr("1111111111111111111111111111111111111"), - errors.ErrLabelTooLong, - }, - { - util.StrToPtr("test:"), - errors.ErrLabelContainsColon, - }, - } - for i, test := range tests { - err := Partition{Label: test.in}.validateLabel() - if err != test.out { - t.Errorf("#%d: wanted %v, got %v", i, test.out, err) - } - } -} - -func TestValidateGUID(t *testing.T) { - tests := []struct { - in *string - out error - }{ - { - util.StrToPtr("5DFBF5F4-2848-4BAC-AA5E-0D9A20B745A6"), - nil, - }, - { - util.StrToPtr("5dfbf5f4-2848-4bac-aa5e-0d9a20b745a6"), - nil, - }, - { - util.StrToPtr(""), - nil, - }, - { - nil, - nil, - }, - { - util.StrToPtr("not-a-valid-typeguid"), - errors.ErrDoesntMatchGUIDRegex, - }, - } - for i, test := range tests { - err := validateGUID(test.in) - if err != test.out { - t.Errorf("#%d: wanted %v, got %v", i, test.out, err) - } - } -} diff --git a/config/v3_5_experimental/types/passwd.go b/config/v3_5_experimental/types/passwd.go deleted file mode 100644 index 4060a2a6f..000000000 --- a/config/v3_5_experimental/types/passwd.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -func (p PasswdUser) Key() string { - return p.Name -} - -func (g PasswdGroup) Key() string { - return g.Name -} diff --git a/config/v3_5_experimental/types/path.go b/config/v3_5_experimental/types/path.go deleted file mode 100644 index 131e300c1..000000000 --- a/config/v3_5_experimental/types/path.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "path" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" -) - -func validatePath(p string) error { - if p == "" { - return errors.ErrNoPath - } - if !path.IsAbs(p) { - return errors.ErrPathRelative - } - if path.Clean(p) != p { - return errors.ErrDirtyPath - } - return nil -} - -func validatePathNilOK(p *string) error { - if util.NilOrEmpty(p) { - return nil - } - return validatePath(*p) -} diff --git a/config/v3_5_experimental/types/path_test.go b/config/v3_5_experimental/types/path_test.go deleted file mode 100644 index 3d199cbdf..000000000 --- a/config/v3_5_experimental/types/path_test.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "reflect" - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" -) - -func TestPathValidate(t *testing.T) { - tests := []struct { - in string - out error - }{ - { - "/good/path", - nil, - }, - { - "/name", - nil, - }, - { - "/this/is/a/fairly/long/path/to/a/device.", - nil, - }, - { - "/this one has spaces", - nil, - }, - { - "relative/path", - errors.ErrPathRelative, - }, - } - - for i, test := range tests { - err := validatePath(test.in) - if !reflect.DeepEqual(test.out, err) { - t.Errorf("#%d: bad error: want %v, got %v", i, test.out, err) - } - } -} diff --git a/config/v3_5_experimental/types/proxy.go b/config/v3_5_experimental/types/proxy.go deleted file mode 100644 index d48d210a0..000000000 --- a/config/v3_5_experimental/types/proxy.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "net/url" - - "github.com/coreos/ignition/v2/config/shared/errors" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (p Proxy) Validate(c path.ContextPath) (r report.Report) { - validateProxyURL(p.HTTPProxy, c.Append("httpProxy"), &r, true) - validateProxyURL(p.HTTPSProxy, c.Append("httpsProxy"), &r, false) - return -} - -func validateProxyURL(s *string, p path.ContextPath, r *report.Report, httpOk bool) { - if s == nil { - return - } - u, err := url.Parse(*s) - if err != nil { - r.AddOnError(p, errors.ErrInvalidUrl) - return - } - - if u.Scheme != "https" && u.Scheme != "http" { - r.AddOnError(p, errors.ErrInvalidProxy) - return - } - if u.Scheme == "http" && !httpOk { - r.AddOnWarn(p, errors.ErrInsecureProxy) - } -} diff --git a/config/v3_5_experimental/types/proxy_test.go b/config/v3_5_experimental/types/proxy_test.go deleted file mode 100644 index 269f4fb22..000000000 --- a/config/v3_5_experimental/types/proxy_test.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "reflect" - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func TestValidateProxyURL(t *testing.T) { - tests := []struct { - in *string - httpOk bool - out report.Entry - }{ - { - nil, - false, - report.Entry{}, - }, - { - nil, - true, - report.Entry{}, - }, - { - util.StrToPtr("https://example.com"), - false, - report.Entry{}, - }, - { - util.StrToPtr("https://example.com"), - true, - report.Entry{}, - }, - { - util.StrToPtr("http://example.com"), - false, - report.Entry{ - Kind: report.Warn, - Message: errors.ErrInsecureProxy.Error(), - }, - }, - { - util.StrToPtr("http://example.com"), - true, - report.Entry{}, - }, - { - util.StrToPtr("ftp://example.com"), - false, - report.Entry{ - Kind: report.Error, - Message: errors.ErrInvalidProxy.Error(), - }, - }, - { - util.StrToPtr("ftp://example.com"), - true, - report.Entry{ - Kind: report.Error, - Message: errors.ErrInvalidProxy.Error(), - }, - }, - { - util.StrToPtr("http://[::1]a"), - false, - report.Entry{ - Kind: report.Error, - Message: errors.ErrInvalidUrl.Error(), - }, - }, - { - util.StrToPtr("http://[::1]a"), - true, - report.Entry{ - Kind: report.Error, - Message: errors.ErrInvalidUrl.Error(), - }, - }, - } - - for i, test := range tests { - r := report.Report{} - validateProxyURL(test.in, path.New(""), &r, test.httpOk) - e := report.Entry{} - if len(r.Entries) > 0 { - e = r.Entries[0] - } - if !reflect.DeepEqual(test.out, e) { - t.Errorf("#%d: bad error: want %v, got %v", i, test.out, e) - } - } -} diff --git a/config/v3_5_experimental/types/raid.go b/config/v3_5_experimental/types/raid.go deleted file mode 100644 index 9d69aa366..000000000 --- a/config/v3_5_experimental/types/raid.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (r Raid) Key() string { - return r.Name -} - -func (r Raid) IgnoreDuplicates() map[string]struct{} { - return map[string]struct{}{ - "Options": {}, - } -} - -func (ra Raid) Validate(c path.ContextPath) (r report.Report) { - r.AddOnError(c.Append("level"), ra.validateLevel()) - if len(ra.Devices) == 0 { - r.AddOnError(c.Append("devices"), errors.ErrRaidDevicesRequired) - } - return -} - -func (r Raid) validateLevel() error { - if util.NilOrEmpty(r.Level) { - return errors.ErrRaidLevelRequired - } - switch *r.Level { - case "linear", "raid0", "0", "stripe": - if r.Spares != nil && *r.Spares != 0 { - return errors.ErrSparesUnsupportedForLevel - } - case "raid1", "1", "mirror": - case "raid4", "4": - case "raid5", "5": - case "raid6", "6": - case "raid10", "10": - default: - return errors.ErrUnrecognizedRaidLevel - } - - return nil -} diff --git a/config/v3_5_experimental/types/raid_test.go b/config/v3_5_experimental/types/raid_test.go deleted file mode 100644 index 7323b26fb..000000000 --- a/config/v3_5_experimental/types/raid_test.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2021 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "reflect" - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func TestRaidValidate(t *testing.T) { - tests := []struct { - in Raid - at path.ContextPath - out error - }{ - { - in: Raid{ - Name: "name", - Level: util.StrToPtr("0"), - Devices: []Device{"/dev/fd0"}, - Spares: util.IntToPtr(0), - }, - out: nil, - }, - { - in: Raid{ - Name: "name", - Devices: []Device{"/dev/fd0"}, - }, - at: path.New("", "level"), - out: errors.ErrRaidLevelRequired, - }, - { - in: Raid{ - Name: "name", - Level: util.StrToPtr("0"), - Devices: []Device{"/dev/fd0"}, - Spares: util.IntToPtr(1), - }, - at: path.New("", "level"), - out: errors.ErrSparesUnsupportedForLevel, - }, - { - in: Raid{ - Name: "name", - Devices: []Device{"/dev/fd0"}, - Level: util.StrToPtr("zzz"), - }, - at: path.New("", "level"), - out: errors.ErrUnrecognizedRaidLevel, - }, - { - in: Raid{ - Name: "name", - Level: util.StrToPtr("0"), - }, - at: path.New("", "devices"), - out: errors.ErrRaidDevicesRequired, - }, - } - - for i, test := range tests { - r := test.in.Validate(path.ContextPath{}) - expected := report.Report{} - expected.AddOnError(test.at, test.out) - if !reflect.DeepEqual(expected, r) { - t.Errorf("#%d: bad report: want %v, got %v", i, expected, r) - } - } -} diff --git a/config/v3_5_experimental/types/resource.go b/config/v3_5_experimental/types/resource.go deleted file mode 100644 index 68da6c7b7..000000000 --- a/config/v3_5_experimental/types/resource.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "net/url" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (res Resource) Key() string { - if res.Source == nil { - return "" - } - return *res.Source -} - -func (res Resource) Validate(c path.ContextPath) (r report.Report) { - r.AddOnError(c.Append("compression"), res.validateCompression()) - r.AddOnError(c.Append("verification", "hash"), res.validateVerification()) - r.AddOnError(c.Append("source"), validateURLNilOK(res.Source)) - r.AddOnError(c.Append("httpHeaders"), res.validateSchemeForHTTPHeaders()) - return -} - -func (res Resource) validateCompression() error { - if res.Compression != nil { - switch *res.Compression { - case "", "gzip": - default: - return errors.ErrCompressionInvalid - } - } - return nil -} - -func (res Resource) validateVerification() error { - if res.Verification.Hash != nil && res.Source == nil { - return errors.ErrVerificationAndNilSource - } - return nil -} - -func (res Resource) validateSchemeForHTTPHeaders() error { - if len(res.HTTPHeaders) < 1 { - return nil - } - - if util.NilOrEmpty(res.Source) { - return errors.ErrInvalidUrl - } - - u, err := url.Parse(*res.Source) - if err != nil { - return errors.ErrInvalidUrl - } - - switch u.Scheme { - case "http", "https": - return nil - default: - return errors.ErrUnsupportedSchemeForHTTPHeaders - } -} - -// Ensure that the Source is specified and valid. This is not called by -// Resource.Validate() because some structs that embed Resource don't -// require Source to be specified. Containing structs that require Source -// should call this function from their Validate(). -func (res Resource) validateRequiredSource() error { - if util.NilOrEmpty(res.Source) { - return errors.ErrSourceRequired - } - return validateURL(*res.Source) -} diff --git a/config/v3_5_experimental/types/schema.go b/config/v3_5_experimental/types/schema.go deleted file mode 100644 index 829578384..000000000 --- a/config/v3_5_experimental/types/schema.go +++ /dev/null @@ -1,264 +0,0 @@ -package types - -// generated by "schematyper --package=types config/v3_5_experimental/schema/ignition.json -o config/v3_5_experimental/types/schema.go --root-type=Config" -- DO NOT EDIT - -type Cex struct { - Enabled *bool `json:"enabled,omitempty"` -} - -type Clevis struct { - Custom ClevisCustom `json:"custom,omitempty"` - Tang []Tang `json:"tang,omitempty"` - Threshold *int `json:"threshold,omitempty"` - Tpm2 *bool `json:"tpm2,omitempty"` -} - -type ClevisCustom struct { - Config *string `json:"config,omitempty"` - NeedsNetwork *bool `json:"needsNetwork,omitempty"` - Pin *string `json:"pin,omitempty"` -} - -type Config struct { - Ignition Ignition `json:"ignition"` - KernelArguments KernelArguments `json:"kernelArguments,omitempty"` - Passwd Passwd `json:"passwd,omitempty"` - Storage Storage `json:"storage,omitempty"` - Systemd Systemd `json:"systemd,omitempty"` -} - -type Device string - -type Directory struct { - Node - DirectoryEmbedded1 -} - -type DirectoryEmbedded1 struct { - Mode *int `json:"mode,omitempty"` -} - -type Disk struct { - Device string `json:"device"` - Partitions []Partition `json:"partitions,omitempty"` - WipeTable *bool `json:"wipeTable,omitempty"` -} - -type Dropin struct { - Contents *string `json:"contents,omitempty"` - Name string `json:"name"` -} - -type File struct { - Node - FileEmbedded1 -} - -type FileEmbedded1 struct { - Append []Resource `json:"append,omitempty"` - Contents Resource `json:"contents,omitempty"` - Mode *int `json:"mode,omitempty"` -} - -type Filesystem struct { - Device string `json:"device"` - Format *string `json:"format,omitempty"` - Label *string `json:"label,omitempty"` - MountOptions []MountOption `json:"mountOptions,omitempty"` - Options []FilesystemOption `json:"options,omitempty"` - Path *string `json:"path,omitempty"` - UUID *string `json:"uuid,omitempty"` - WipeFilesystem *bool `json:"wipeFilesystem,omitempty"` -} - -type FilesystemOption string - -type Group string - -type HTTPHeader struct { - Name string `json:"name"` - Value *string `json:"value,omitempty"` -} - -type HTTPHeaders []HTTPHeader - -type Ignition struct { - Config IgnitionConfig `json:"config,omitempty"` - Proxy Proxy `json:"proxy,omitempty"` - Security Security `json:"security,omitempty"` - Timeouts Timeouts `json:"timeouts,omitempty"` - Version string `json:"version"` -} - -type IgnitionConfig struct { - Merge []Resource `json:"merge,omitempty"` - Replace Resource `json:"replace,omitempty"` -} - -type KernelArgument string - -type KernelArguments struct { - ShouldExist []KernelArgument `json:"shouldExist,omitempty"` - ShouldNotExist []KernelArgument `json:"shouldNotExist,omitempty"` -} - -type Link struct { - Node - LinkEmbedded1 -} - -type LinkEmbedded1 struct { - Hard *bool `json:"hard,omitempty"` - Target *string `json:"target,omitempty"` -} - -type Luks struct { - Cex Cex `json:"cex,omitempty"` - Clevis Clevis `json:"clevis,omitempty"` - Device *string `json:"device,omitempty"` - Discard *bool `json:"discard,omitempty"` - KeyFile Resource `json:"keyFile,omitempty"` - Label *string `json:"label,omitempty"` - Name string `json:"name"` - OpenOptions []OpenOption `json:"openOptions,omitempty"` - Options []LuksOption `json:"options,omitempty"` - UUID *string `json:"uuid,omitempty"` - WipeVolume *bool `json:"wipeVolume,omitempty"` -} - -type LuksOption string - -type MountOption string - -type NoProxyItem string - -type Node struct { - Group NodeGroup `json:"group,omitempty"` - Overwrite *bool `json:"overwrite,omitempty"` - Path string `json:"path"` - User NodeUser `json:"user,omitempty"` -} - -type NodeGroup struct { - ID *int `json:"id,omitempty"` - Name *string `json:"name,omitempty"` -} - -type NodeUser struct { - ID *int `json:"id,omitempty"` - Name *string `json:"name,omitempty"` -} - -type OpenOption string - -type Partition struct { - GUID *string `json:"guid,omitempty"` - Label *string `json:"label,omitempty"` - Number int `json:"number,omitempty"` - Resize *bool `json:"resize,omitempty"` - ShouldExist *bool `json:"shouldExist,omitempty"` - SizeMiB *int `json:"sizeMiB,omitempty"` - StartMiB *int `json:"startMiB,omitempty"` - TypeGUID *string `json:"typeGuid,omitempty"` - WipePartitionEntry *bool `json:"wipePartitionEntry,omitempty"` -} - -type Passwd struct { - Groups []PasswdGroup `json:"groups,omitempty"` - Users []PasswdUser `json:"users,omitempty"` -} - -type PasswdGroup struct { - Gid *int `json:"gid,omitempty"` - Name string `json:"name"` - PasswordHash *string `json:"passwordHash,omitempty"` - ShouldExist *bool `json:"shouldExist,omitempty"` - System *bool `json:"system,omitempty"` -} - -type PasswdUser struct { - Gecos *string `json:"gecos,omitempty"` - Groups []Group `json:"groups,omitempty"` - HomeDir *string `json:"homeDir,omitempty"` - Name string `json:"name"` - NoCreateHome *bool `json:"noCreateHome,omitempty"` - NoLogInit *bool `json:"noLogInit,omitempty"` - NoUserGroup *bool `json:"noUserGroup,omitempty"` - PasswordHash *string `json:"passwordHash,omitempty"` - PrimaryGroup *string `json:"primaryGroup,omitempty"` - SSHAuthorizedKeys []SSHAuthorizedKey `json:"sshAuthorizedKeys,omitempty"` - Shell *string `json:"shell,omitempty"` - ShouldExist *bool `json:"shouldExist,omitempty"` - System *bool `json:"system,omitempty"` - UID *int `json:"uid,omitempty"` -} - -type Proxy struct { - HTTPProxy *string `json:"httpProxy,omitempty"` - HTTPSProxy *string `json:"httpsProxy,omitempty"` - NoProxy []NoProxyItem `json:"noProxy,omitempty"` -} - -type Raid struct { - Devices []Device `json:"devices,omitempty"` - Level *string `json:"level,omitempty"` - Name string `json:"name"` - Options []RaidOption `json:"options,omitempty"` - Spares *int `json:"spares,omitempty"` -} - -type RaidOption string - -type Resource struct { - Compression *string `json:"compression,omitempty"` - HTTPHeaders HTTPHeaders `json:"httpHeaders,omitempty"` - Source *string `json:"source,omitempty"` - Verification Verification `json:"verification,omitempty"` -} - -type SSHAuthorizedKey string - -type Security struct { - TLS TLS `json:"tls,omitempty"` -} - -type Storage struct { - Directories []Directory `json:"directories,omitempty"` - Disks []Disk `json:"disks,omitempty"` - Files []File `json:"files,omitempty"` - Filesystems []Filesystem `json:"filesystems,omitempty"` - Links []Link `json:"links,omitempty"` - Luks []Luks `json:"luks,omitempty"` - Raid []Raid `json:"raid,omitempty"` -} - -type Systemd struct { - Units []Unit `json:"units,omitempty"` -} - -type TLS struct { - CertificateAuthorities []Resource `json:"certificateAuthorities,omitempty"` -} - -type Tang struct { - Advertisement *string `json:"advertisement,omitempty"` - Thumbprint *string `json:"thumbprint,omitempty"` - URL string `json:"url,omitempty"` -} - -type Timeouts struct { - HTTPResponseHeaders *int `json:"httpResponseHeaders,omitempty"` - HTTPTotal *int `json:"httpTotal,omitempty"` -} - -type Unit struct { - Contents *string `json:"contents,omitempty"` - Dropins []Dropin `json:"dropins,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - Mask *bool `json:"mask,omitempty"` - Name string `json:"name"` -} - -type Verification struct { - Hash *string `json:"hash,omitempty"` -} diff --git a/config/v3_5_experimental/types/storage.go b/config/v3_5_experimental/types/storage.go deleted file mode 100644 index 20cb73048..000000000 --- a/config/v3_5_experimental/types/storage.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "path" - "strings" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - vpath "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (s Storage) MergedKeys() map[string]string { - return map[string]string{ - "Directories": "Node", - "Files": "Node", - "Links": "Node", - } -} - -func (s Storage) Validate(c vpath.ContextPath) (r report.Report) { - s.validateDirectories(c, &r) - s.validateFiles(c, &r) - s.validateLinks(c, &r) - s.validateFilesystems(c, &r) - return -} - -func (s Storage) validateDirectories(c vpath.ContextPath, r *report.Report) { - for i, d := range s.Directories { - for _, l := range s.Links { - if strings.HasPrefix(d.Path, l.Path+"/") { - r.AddOnError(c.Append("directories", i), errors.ErrDirectoryUsedSymlink) - } - } - } -} - -func (s Storage) validateFiles(c vpath.ContextPath, r *report.Report) { - for i, f := range s.Files { - for _, l := range s.Links { - if strings.HasPrefix(f.Path, l.Path+"/") { - r.AddOnError(c.Append("files", i), errors.ErrFileUsedSymlink) - } - } - } -} - -func (s Storage) validateLinks(c vpath.ContextPath, r *report.Report) { - for i, l1 := range s.Links { - for _, l2 := range s.Links { - if strings.HasPrefix(l1.Path, l2.Path+"/") { - r.AddOnError(c.Append("links", i), errors.ErrLinkUsedSymlink) - } - } - if util.NilOrEmpty(l1.Target) { - r.AddOnError(c.Append("links", i, "target"), errors.ErrLinkTargetRequired) - continue - } - if !util.IsTrue(l1.Hard) { - continue - } - target := path.Clean(*l1.Target) - if !path.IsAbs(target) { - target = path.Join(l1.Path, *l1.Target) - } - for _, d := range s.Directories { - if target == d.Path { - r.AddOnError(c.Append("links", i), errors.ErrHardLinkToDirectory) - } - } - ownerCheck := func(ok bool, path vpath.ContextPath) { - if !ok { - r.AddOnWarn(path, errors.ErrHardLinkSpecifiesOwner) - } - } - ownerCheck(l1.User.ID == nil, c.Append("links", i, "user", "id")) - ownerCheck(l1.User.Name == nil, c.Append("links", i, "user", "name")) - ownerCheck(l1.Group.ID == nil, c.Append("links", i, "group", "id")) - ownerCheck(l1.Group.Name == nil, c.Append("links", i, "group", "name")) - } -} - -func (s Storage) validateFilesystems(c vpath.ContextPath, r *report.Report) { - disks := make(map[string]Disk) - for _, d := range s.Disks { - disks[d.Device] = d - } - - for i, f := range s.Filesystems { - disk, exist := disks[f.Device] - if exist { - if len(disk.Partitions) > 0 { - r.AddOnWarn(c.Append("filesystems", i, "device"), errors.ErrPartitionsOverwritten) - } else if !util.IsTrue(f.WipeFilesystem) && util.IsTrue(disk.WipeTable) { - r.AddOnWarn(c.Append("filesystems", i, "device"), errors.ErrFilesystemImplicitWipe) - } - } - } -} diff --git a/config/v3_5_experimental/types/storage_test.go b/config/v3_5_experimental/types/storage_test.go deleted file mode 100644 index 551688a27..000000000 --- a/config/v3_5_experimental/types/storage_test.go +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "reflect" - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func TestStorageValidateErrors(t *testing.T) { - tests := []struct { - in Storage - at path.ContextPath - err error - warn error - }{ - // test empty storage config returns nil - { - in: Storage{}, - }, - // test a storage config with no conflicting paths returns nil - { - in: Storage{ - Links: []Link{ - { - Node: Node{Path: "/foo"}, - LinkEmbedded1: LinkEmbedded1{Target: util.StrToPtr("/foo-t")}, - }, - { - Node: Node{Path: "/quux"}, - LinkEmbedded1: LinkEmbedded1{Target: util.StrToPtr("/quux-t")}, - }, - }, - Files: []File{ - { - Node: Node{Path: "/bar"}, - }, - }, - Directories: []Directory{ - { - Node: Node{Path: "/baz"}, - }, - }, - }, - }, - // test when a file uses a configured symlink path returns ErrFileUsedSymlink - { - in: Storage{ - Links: []Link{ - { - Node: Node{Path: "/foo"}, - LinkEmbedded1: LinkEmbedded1{Target: util.StrToPtr("/foo-t")}, - }, - }, - Files: []File{ - { - Node: Node{Path: "/foo/bar"}, - }, - }, - }, - err: errors.ErrFileUsedSymlink, - at: path.New("", "files", 0), - }, - // test when a directory uses a configured symlink path returns ErrDirectoryUsedSymlink - { - in: Storage{ - Links: []Link{ - { - Node: Node{Path: "/foo"}, - LinkEmbedded1: LinkEmbedded1{Target: util.StrToPtr("/foo-t")}, - }, - }, - Directories: []Directory{ - { - Node: Node{Path: "/foo/bar"}, - }, - }, - }, - err: errors.ErrDirectoryUsedSymlink, - at: path.New("", "directories", 0), - }, - // test the same path listed for two separate symlinks returns ErrLinkUsedSymlink - { - in: Storage{ - Links: []Link{ - { - Node: Node{Path: "/foo"}, - LinkEmbedded1: LinkEmbedded1{Target: util.StrToPtr("/foo-t")}, - }, - { - Node: Node{Path: "/foo/bar"}, - LinkEmbedded1: LinkEmbedded1{Target: util.StrToPtr("/foo-bar-t")}, - }, - }, - }, - err: errors.ErrLinkUsedSymlink, - at: path.New("", "links", 1), - }, - // test a configured symlink with no target returns ErrLinkTargetRequired - { - in: Storage{ - Links: []Link{ - { - Node: Node{Path: "/foo"}, - LinkEmbedded1: LinkEmbedded1{Hard: util.BoolToPtr(true)}, - }, - }, - }, - err: errors.ErrLinkTargetRequired, - at: path.New("", "links", 0, "target"), - }, - // test a configured symlink with a nil target returns ErrLinkTargetRequired - { - in: Storage{ - Links: []Link{ - { - Node: Node{Path: "/foo"}, - LinkEmbedded1: LinkEmbedded1{Target: util.StrToPtr("")}, - }, - }, - }, - err: errors.ErrLinkTargetRequired, - at: path.New("", "links", 0, "target"), - }, - // test that two symlinks can be configured at a time - { - in: Storage{ - Links: []Link{ - { - Node: Node{Path: "/foo"}, - LinkEmbedded1: LinkEmbedded1{Target: util.StrToPtr("/foo-t")}, - }, - { - Node: Node{Path: "/foob/bar"}, - LinkEmbedded1: LinkEmbedded1{Target: util.StrToPtr("/foob-bar-t")}, - }, - }, - }, - }, - // test when a directory uses a configured symlink with the 'Hard:= true' returns ErrHardLinkToDirectory - { - in: Storage{ - Links: []Link{ - { - Node: Node{Path: "/quux"}, - LinkEmbedded1: LinkEmbedded1{ - Target: util.StrToPtr("/foo/bar"), - Hard: util.BoolToPtr(true), - }, - }, - }, - Directories: []Directory{ - { - Node: Node{Path: "/foo/bar"}, - }, - }, - }, - err: errors.ErrHardLinkToDirectory, - at: path.New("", "links", 0), - }, - { - in: Storage{ - Links: []Link{ - { - Node: Node{ - Path: "/quux", - User: NodeUser{ - ID: util.IntToPtr(10), - }, - }, - LinkEmbedded1: LinkEmbedded1{ - Target: util.StrToPtr("/foo/bar"), - Hard: util.BoolToPtr(true), - }, - }, - }, - }, - warn: errors.ErrHardLinkSpecifiesOwner, - at: path.New("", "links", 0, "user", "id"), - }, - { - in: Storage{ - Links: []Link{ - { - Node: Node{ - Path: "/quux", - User: NodeUser{ - Name: util.StrToPtr("bovik"), - }, - }, - LinkEmbedded1: LinkEmbedded1{ - Target: util.StrToPtr("/foo/bar"), - Hard: util.BoolToPtr(true), - }, - }, - }, - }, - warn: errors.ErrHardLinkSpecifiesOwner, - at: path.New("", "links", 0, "user", "name"), - }, - { - in: Storage{ - Links: []Link{ - { - Node: Node{ - Path: "/quux", - Group: NodeGroup{ - ID: util.IntToPtr(10), - }, - }, - LinkEmbedded1: LinkEmbedded1{ - Target: util.StrToPtr("/foo/bar"), - Hard: util.BoolToPtr(true), - }, - }, - }, - }, - warn: errors.ErrHardLinkSpecifiesOwner, - at: path.New("", "links", 0, "group", "id"), - }, - { - in: Storage{ - Links: []Link{ - { - Node: Node{ - Path: "/quux", - Group: NodeGroup{ - Name: util.StrToPtr("bovik"), - }, - }, - LinkEmbedded1: LinkEmbedded1{ - Target: util.StrToPtr("/foo/bar"), - Hard: util.BoolToPtr(true), - }, - }, - }, - }, - warn: errors.ErrHardLinkSpecifiesOwner, - at: path.New("", "links", 0, "group", "name"), - }, - } - - for i, test := range tests { - r := test.in.Validate(path.ContextPath{}) - expected := report.Report{} - expected.AddOnError(test.at, test.err) - expected.AddOnWarn(test.at, test.warn) - if !reflect.DeepEqual(expected, r) { - t.Errorf("#%d: bad report: want %v, got %v", i, expected, r) - } - } -} - -func TestStorageValidateWarnings(t *testing.T) { - tests := []struct { - in Storage - at path.ContextPath - out error - }{ - // test a disk with partitions with the same 'device' as a filesystem returns ErrPartitionsOverwritten - { - in: Storage{ - Disks: []Disk{ - { - Device: "/dev/sda", - Partitions: []Partition{ - {}, {}, - }, - }, - }, - Filesystems: []Filesystem{ - { - Device: "/dev/sda", - }, - }, - }, - out: errors.ErrPartitionsOverwritten, - at: path.New("", "filesystems", 0, "device"), - }, - // test a disk with the same 'device' and 'WipeTable:=true' as a configured filesystem returns ErrFilesystemImplicitWipe - { - in: Storage{ - Disks: []Disk{ - { - Device: "/dev/sda", - WipeTable: util.BoolToPtr(true), - }, - }, - Filesystems: []Filesystem{ - { - Device: "/dev/sda", - }, - }, - }, - out: errors.ErrFilesystemImplicitWipe, - at: path.New("", "filesystems", 0, "device"), - }, - // test a disk with the same 'device' and 'WipeTable:=false' as a configured filesystem returns nil - { - in: Storage{ - Disks: []Disk{ - { - Device: "/dev/sda", - WipeTable: util.BoolToPtr(false), - }, - }, - Filesystems: []Filesystem{ - { - Device: "/dev/sda", - }, - }, - }, - out: nil, - }, - // test a disk with no partitions with the same 'device' as a filesystem returns nil - { - in: Storage{ - Disks: []Disk{ - { - Device: "/dev/sdb", - }, - }, - Filesystems: []Filesystem{ - { - Device: "/dev/sdb", - }, - }, - }, - out: nil, - }, - } - - for i, test := range tests { - r := test.in.Validate(path.ContextPath{}) - expected := report.Report{} - expected.AddOnWarn(test.at, test.out) - if !reflect.DeepEqual(expected, r) { - t.Errorf("#%d: bad report: want %v, got %v", i, expected, r) - } - } -} diff --git a/config/v3_5_experimental/types/systemd.go b/config/v3_5_experimental/types/systemd.go deleted file mode 100644 index ac521ba73..000000000 --- a/config/v3_5_experimental/types/systemd.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2022 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "regexp" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/shared/parse" - "github.com/coreos/ignition/v2/config/util" - - vpath "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (s Systemd) Validate(c vpath.ContextPath) (r report.Report) { - units := make(map[string]Unit) - checkInstanceUnit := regexp.MustCompile(`^(.+?)@(.+?)\.service$`) - for _, d := range s.Units { - units[d.Name] = d - } - for index, unit := range s.Units { - if checkInstanceUnit.MatchString(unit.Name) && util.IsTrue(unit.Enabled) { - instUnitSlice := checkInstanceUnit.FindSubmatch([]byte(unit.Name)) - instantiableUnit := string(instUnitSlice[1]) + "@.service" - if _, ok := units[instantiableUnit]; ok && util.NotEmpty(units[instantiableUnit].Contents) { - foundInstallSection := false - // we're doing a separate validation pass on each unit to identify - // if an instantiable unit has the install section. So logging an - // `AddOnError` will produce duplicate errors on bad unit contents - // because we're already doing that while validating a unit separately. - opts, err := parse.ParseUnitContents(units[instantiableUnit].Contents) - if err != nil { - continue - } - for _, section := range opts { - if section.Section == "Install" { - foundInstallSection = true - break - } - } - if !foundInstallSection { - r.AddOnWarn(c.Append("units", index, "contents"), errors.NewNoInstallSectionForInstantiableUnitError(instantiableUnit, unit.Name)) - } - } - } - } - return -} diff --git a/config/v3_5_experimental/types/systemd_test.go b/config/v3_5_experimental/types/systemd_test.go deleted file mode 100644 index 798eb10f4..000000000 --- a/config/v3_5_experimental/types/systemd_test.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2022 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "fmt" - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" - "github.com/stretchr/testify/assert" -) - -func TestSystemdValidate(t *testing.T) { - tests := []struct { - in Systemd - out error - }{ - { - Systemd{ - []Unit{ - {Name: "test@.service", Contents: util.StrToPtr("[Foo]\nQux=Bar")}, - {Name: "test@foo.service", Enabled: util.BoolToPtr(true)}, - }, - }, - errors.NewNoInstallSectionForInstantiableUnitError("test@.service", "test@foo.service"), - }, - { - Systemd{ - []Unit{ - {Name: "test2@.service", Contents: util.StrToPtr("[Foo]\nQux=Bar")}, - }, - }, - nil, - }, - { - Systemd{ - []Unit{ - {Name: "test@.service", Contents: util.StrToPtr("[Foo]\nQux=Bar")}, - {Name: "test@foo.service", Enabled: util.BoolToPtr(false)}, - }, - }, - nil, - }, - { - Systemd{ - []Unit{ - {Name: "test2@.service", Contents: util.StrToPtr("[Unit]\nDescription=echo service template\n[Service]\nType=oneshot\nExecStart=/bin/echo %i\n[Install]\nWantedBy=multi-user.target\n")}, - {Name: "test2@foo.service", Enabled: util.BoolToPtr(false)}, - }, - }, - nil, - }, - { - Systemd{ - []Unit{ - {Name: "test2@.service", Contents: util.StrToPtr("[Unit]\nDescription=echo service template\n[Service]\nType=oneshot\nExecStart=/bin/echo %i\n[Install]\nWantedBy=multi-user.target\n")}, - {Name: "test2@bar.service", Enabled: util.BoolToPtr(true)}, - }, - }, - nil, - }, - { - Systemd{ - []Unit{ - {Name: "test@.service", Contents: util.StrToPtr("[Unit]\nDescription=echo service template\n[Service]\nType=oneshot\nExecStart=/bin/echo %i\n[Install]\nWantedBy=multi-user.target\n")}, - {Name: "test2@foo.service", Enabled: util.BoolToPtr(true)}, - }, - }, - nil, - }, - { - Systemd{ - []Unit{ - {Name: "test@.service"}, - {Name: "test@bar.service", Enabled: util.BoolToPtr(true)}, - }, - }, - nil, - }, - } - - for i, test := range tests { - t.Run(fmt.Sprintf("validate %d", i), func(t *testing.T) { - actual := test.in.Validate(path.ContextPath{}) - expected := report.Report{} - expected.AddOnWarn(path.ContextPath{}.Append("units", 1, "contents"), test.out) - assert.Equal(t, expected, actual, "bad report") - }) - } -} diff --git a/config/v3_5_experimental/types/tang.go b/config/v3_5_experimental/types/tang.go deleted file mode 100644 index 1839d6cc3..000000000 --- a/config/v3_5_experimental/types/tang.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "encoding/json" - "net/url" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (t Tang) Key() string { - return t.URL -} - -func (t Tang) Validate(c path.ContextPath) (r report.Report) { - r.AddOnError(c.Append("url"), validateTangURL(t.URL)) - if util.NilOrEmpty(t.Thumbprint) { - r.AddOnError(c.Append("thumbprint"), errors.ErrTangThumbprintRequired) - } - r.AddOnError(c.Append("advertisement"), validateTangAdvertisement(t.Advertisement)) - return -} - -func validateTangURL(s string) error { - u, err := url.Parse(s) - if err != nil { - return errors.ErrInvalidUrl - } - - switch u.Scheme { - case "http", "https": - return nil - default: - return errors.ErrInvalidScheme - } -} - -func validateTangAdvertisement(s *string) error { - if util.NotEmpty(s) { - var adv any - err := json.Unmarshal([]byte(*s), &adv) - if err != nil { - return errors.ErrInvalidTangAdvertisement - } - } - - return nil -} diff --git a/config/v3_5_experimental/types/tang_test.go b/config/v3_5_experimental/types/tang_test.go deleted file mode 100644 index fb57b1e4a..000000000 --- a/config/v3_5_experimental/types/tang_test.go +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "reflect" - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func TestTangValidation(t *testing.T) { - tests := []struct { - in Tang - out error - at path.ContextPath - }{ - // happy path with no advertisement and healthy url - { - in: Tang{ - URL: "http://example.com", - Thumbprint: util.StrToPtr("abc"), - }, - out: nil, - }, - // test 1: invalid url scheme - { - in: Tang{ - URL: "httasfdsafadsf", - Thumbprint: util.StrToPtr("abc"), - }, - out: errors.ErrInvalidScheme, - at: path.New("foo", "url"), - }, - // null url - { - in: Tang{ - Thumbprint: util.StrToPtr("abc"), - }, - out: errors.ErrInvalidScheme, - at: path.New("foo", "url"), - }, - // null thumbprint - { - in: Tang{ - URL: "http://example.com", - Thumbprint: nil, - }, - out: errors.ErrTangThumbprintRequired, - at: path.New("foo", "thumbprint"), - }, - // Advertisement is valid json - { - in: Tang{ - URL: "http://example.com", - Thumbprint: util.StrToPtr("abc"), - Advertisement: util.StrToPtr("{\"payload\": \"eyJrZXlzIjogW3siYWxnIjogIkVTNTEyIiwgImt0eSI6ICJFQyIsICJjcnYiOiAiUC01MjEiLCAieCI6ICJBRGFNajJmazNob21CWTF5WElSQ21uRk92cmUzOFZjdHMwTnNHeDZ6RWNxdEVXcjh5ekhUMkhfa2hjNGpSa19FQWFLdjNrd2RjZ05sOTBLcGhfMGYyQ190IiwgInkiOiAiQUZ2d1UyeGJ5T1RydWo0V1NtcVlqN2wtcUVTZmhWakdCNTI1Q2d6d0NoZUZRRTBvb1o3STYyamt3NkRKQ05yS3VPUDRsSEhicm8tYXhoUk9MSXNJVExvNCIsICJrZXlfb3BzIjogWyJ2ZXJpZnkiXX0sIHsiYWxnIjogIkVDTVIiLCAia3R5IjogIkVDIiwgImNydiI6ICJQLTUyMSIsICJ4IjogIkFOZDVYcTFvZklUbTdNWG16OUY0VVRSYmRNZFNIMl9XNXczTDVWZ0w3b3hwdmpyM0hkLXNLNUVqd3A1V2swMnJMb3NXVUJjYkZyZEhjZFJTTVJoZlVFTFIiLCAieSI6ICJBRVVaVlVZWkFBY2hVcmdoX3poaTV3SUUzeTEycGwzeWhqUk5LcGpSdW9tUFhKaDhRaFhXRmRWZEtMUlEwX1lwUjNOMjNSUk1pU1lvWlg0Qm42QnlrQVBMIiwgImtleV9vcHMiOiBbImRlcml2ZUtleSJdfV19\", \"protected\": \"eyJhbGciOiJFUzUxMiIsImN0eSI6Imp3ay1zZXQranNvbiJ9\", \"signature\": \"APHfSyVzLwELwG0pMJyIP74gWvhHUvDtv0SESBxA2uOdSXq76IdWHW2xvCZDdlNan8pnqUvEedPZjf_vdKBw9MTXAPMkRxVnu64HepKwlrzzm_zG2R4CHpoCOsGgjH9-acYxg-Vha63oMojv3_bV0VHg-NbzNLaxietgYplstvcNIwkv\"}"), - }, - out: nil, - }, - // Advertisement is empty string - { - in: Tang{ - URL: "http://example.com", - Thumbprint: util.StrToPtr("abc"), - Advertisement: util.StrToPtr(""), - }, - out: nil, - }, - // Advertisement is not valid json - { - in: Tang{ - URL: "http://example.com", - Thumbprint: util.StrToPtr("abc"), - Advertisement: util.StrToPtr("{{"), - }, - out: errors.ErrInvalidTangAdvertisement, - at: path.New("foo", "advertisement"), - }, - } - for i, test := range tests { - r := test.in.Validate(path.New("foo")) - expected := report.Report{} - expected.AddOnError(test.at, test.out) - if !reflect.DeepEqual(expected, r) { - t.Errorf("#%d: bad error: expected : %v, got %v", i, expected, r) - } - } -} diff --git a/config/v3_5_experimental/types/tls.go b/config/v3_5_experimental/types/tls.go deleted file mode 100644 index 8890e397e..000000000 --- a/config/v3_5_experimental/types/tls.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (tls TLS) Validate(c path.ContextPath) (r report.Report) { - for i, ca := range tls.CertificateAuthorities { - r.AddOnError(c.Append("certificateAuthorities", i), ca.validateRequiredSource()) - } - return -} diff --git a/config/v3_5_experimental/types/tls_test.go b/config/v3_5_experimental/types/tls_test.go deleted file mode 100644 index 8f3b2e351..000000000 --- a/config/v3_5_experimental/types/tls_test.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "testing" - - "github.com/coreos/vcontext/validate" -) - -func TestTLSValidate(t *testing.T) { - tests := []struct { - in TLS - out string - }{ - { - TLS{ - CertificateAuthorities: []Resource{{}}, - }, - "error at $.certificateAuthorities.0: source is required\n", - }, - } - - for i, test := range tests { - r := validate.Validate(test.in, "test") - if test.out != r.String() { - t.Errorf("#%d: bad error: want %q, got %q", i, test.out, r.String()) - } - } -} diff --git a/config/v3_5_experimental/types/unit.go b/config/v3_5_experimental/types/unit.go deleted file mode 100644 index c5ee1e8e3..000000000 --- a/config/v3_5_experimental/types/unit.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "path" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/shared/parse" - "github.com/coreos/ignition/v2/config/shared/validations" - "github.com/coreos/ignition/v2/config/util" - - cpath "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func (u Unit) Key() string { - return u.Name -} - -func (d Dropin) Key() string { - return d.Name -} - -func (u Unit) Validate(c cpath.ContextPath) (r report.Report) { - r.AddOnError(c.Append("name"), validateName(u.Name)) - c = c.Append("contents") - opts, err := parse.ParseUnitContents(u.Contents) - r.AddOnError(c, err) - - r.AddOnWarn(c, validations.ValidateInstallSection(u.Name, util.IsTrue(u.Enabled), util.NilOrEmpty(u.Contents), opts)) - - return -} - -func validateName(name string) error { - switch path.Ext(name) { - case ".service", ".socket", ".device", ".mount", ".automount", ".swap", ".target", ".path", ".timer", ".snapshot", ".slice", ".scope": - default: - return errors.ErrInvalidSystemdExt - } - return nil -} - -func (d Dropin) Validate(c cpath.ContextPath) (r report.Report) { - _, err := parse.ParseUnitContents(d.Contents) - r.AddOnError(c.Append("contents"), err) - - switch path.Ext(d.Name) { - case ".conf": - default: - r.AddOnError(c.Append("name"), errors.ErrInvalidSystemdDropinExt) - } - - return -} diff --git a/config/v3_5_experimental/types/unit_test.go b/config/v3_5_experimental/types/unit_test.go deleted file mode 100644 index 3dc905407..000000000 --- a/config/v3_5_experimental/types/unit_test.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "fmt" - "reflect" - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func TestSystemdUnitValidateContents(t *testing.T) { - tests := []struct { - in Unit - out error - }{ - { - Unit{Name: "test.service", Contents: util.StrToPtr("[Foo]\nQux=Bar")}, - nil, - }, - { - Unit{Name: "test.service", Contents: util.StrToPtr("[Foo")}, - fmt.Errorf("invalid unit content: unable to find end of section"), - }, - { - Unit{Name: "test.service", Contents: util.StrToPtr(""), Dropins: []Dropin{{}}}, - nil, - }, - } - - for i, test := range tests { - err := test.in.Validate(path.ContextPath{}) - expected := report.Report{} - expected.AddOnError(path.New("", "contents"), test.out) - if !reflect.DeepEqual(expected, err) { - t.Errorf("#%d: bad error: want %v, got %v", i, expected, err) - } - } -} - -func TestSystemdUnitValidateName(t *testing.T) { - tests := []struct { - in string - out error - }{ - { - "test.service", - nil, - }, - { - "test.socket", - nil, - }, - { - "test.blah", - errors.ErrInvalidSystemdExt, - }, - } - - for i, test := range tests { - err := validateName(test.in) - if test.out != err { - t.Errorf("#%d: bad error: want %v, got %v", i, test.out, err) - } - } -} - -func TestSystemdUnitDropInValidate(t *testing.T) { - tests := []struct { - in Dropin - out error - }{ - { - Dropin{Name: "test.conf", Contents: util.StrToPtr("[Foo]\nQux=Bar")}, - nil, - }, - { - Dropin{Name: "test.conf", Contents: util.StrToPtr("[Foo")}, - fmt.Errorf("invalid unit content: unable to find end of section"), - }, - } - - for i, test := range tests { - err := test.in.Validate(path.ContextPath{}) - expected := report.Report{} - expected.AddOnError(path.New("", "contents"), test.out) - if !reflect.DeepEqual(expected, err) { - t.Errorf("#%d: bad error: want %v, got %v", i, expected, err) - } - } -} diff --git a/config/v3_5_experimental/types/url.go b/config/v3_5_experimental/types/url.go deleted file mode 100644 index 3ca189dae..000000000 --- a/config/v3_5_experimental/types/url.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "net/url" - "strings" - - "github.com/aws/aws-sdk-go/aws/arn" - "github.com/vincent-petithory/dataurl" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" -) - -func validateURL(s string) error { - u, err := url.Parse(s) - if err != nil { - return errors.ErrInvalidUrl - } - - switch u.Scheme { - case "http", "https", "tftp", "gs": - return nil - case "s3": - if v, ok := u.Query()["versionId"]; ok { - if len(v) == 0 || v[0] == "" { - return errors.ErrInvalidS3ObjectVersionId - } - } - return nil - case "arn": - fullURL := u.Scheme + ":" + u.Opaque - if !arn.IsARN(fullURL) { - return errors.ErrInvalidS3ARN - } - s3arn, err := arn.Parse(fullURL) - if err != nil { - return err - } - if s3arn.Service != "s3" { - return errors.ErrInvalidS3ARN - } - urlSplit := strings.Split(fullURL, "/") - if strings.HasPrefix(s3arn.Resource, "accesspoint/") && len(urlSplit) < 3 { - return errors.ErrInvalidS3ARN - } else if len(urlSplit) < 2 { - return errors.ErrInvalidS3ARN - } - if v, ok := u.Query()["versionId"]; ok { - if len(v) == 0 || v[0] == "" { - return errors.ErrInvalidS3ObjectVersionId - } - } - return nil - case "data": - if _, err := dataurl.DecodeString(s); err != nil { - return err - } - return nil - default: - return errors.ErrInvalidScheme - } -} - -func validateURLNilOK(s *string) error { - if util.NilOrEmpty(s) { - return nil - } - return validateURL(*s) -} diff --git a/config/v3_5_experimental/types/url_test.go b/config/v3_5_experimental/types/url_test.go deleted file mode 100644 index 1901b7aff..000000000 --- a/config/v3_5_experimental/types/url_test.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - "github.com/coreos/ignition/v2/config/util" -) - -func TestURLValidate(t *testing.T) { - tests := []struct { - in *string - out error - }{ - { - nil, - nil, - }, - { - util.StrToPtr(""), - nil, - }, - { - util.StrToPtr("http://example.com"), - nil, - }, - { - util.StrToPtr("https://example.com"), - nil, - }, - { - util.StrToPtr("tftp://example.com:69/foobar.txt"), - nil, - }, - { - util.StrToPtr("data:,example%20file%0A"), - nil, - }, - { - util.StrToPtr("bad://"), - errors.ErrInvalidScheme, - }, - { - util.StrToPtr("s3://bucket/key"), - nil, - }, - { - util.StrToPtr("s3://bucket/key?versionId="), - errors.ErrInvalidS3ObjectVersionId, - }, - { - util.StrToPtr("s3://bucket/key?versionId=aVersionHash"), - nil, - }, - { - util.StrToPtr("Arn:"), - errors.ErrInvalidS3ARN, - }, - { - util.StrToPtr("arn:aws:iam:us-west-2:123456789012:resource"), - errors.ErrInvalidS3ARN, - }, - { - util.StrToPtr("arn:aws:s3:::bucket-name-but-no-key"), - errors.ErrInvalidS3ARN, - }, - { - util.StrToPtr("arn:aws:s3:us-west-2:123456789012:accesspoint"), - errors.ErrInvalidS3ARN, - }, - { - util.StrToPtr("arn:aws:s3:us-west-2:123456789012:accesspoint/"), - errors.ErrInvalidS3ARN, - }, - { - util.StrToPtr("arn:aws:s3:us-west-2:123456789012:accesspoint/accesspoint-name-but-no-bucket"), - errors.ErrInvalidS3ARN, - }, - { - util.StrToPtr("arn:aws:s3:us-west-2:123456789012:bucket-name/object-key"), - nil, - }, - { - util.StrToPtr("arn:aws:s3:us-west-2:123456789012:bucket-name/object-key?versionId=aVersionHash"), - nil, - }, - { - util.StrToPtr("arn:aws:s3:us-west-2:123456789012:accesspoint/accesspoint-name/object"), - nil, - }, - { - util.StrToPtr("arn:aws:s3:us-west-2:123456789012:accesspoint/accesspoint-name/some/nested/object"), - nil, - }, - { - util.StrToPtr("arn:aws:s3:us-west-2:123456789012:accesspoint/accesspoint-name/object?versionId=aVersionHash"), - nil, - }, - { - util.StrToPtr("arn:aws:s3:::bucket-name/object-key"), - nil, - }, - { - util.StrToPtr("arn:aws:s3:::bucket-name/some/nested/object"), - nil, - }, - { - util.StrToPtr("arn:aws:s3:::bucket-name/object-key?versionId=aVersionHash"), - nil, - }, - { - util.StrToPtr("gs://bucket/object"), - nil, - }, - } - - for i, test := range tests { - err := validateURLNilOK(test.in) - if test.out != err { - t.Errorf("#%d: bad error: want %v, got %v", i, test.out, err) - } - } -} diff --git a/config/v3_5_experimental/types/verification.go b/config/v3_5_experimental/types/verification.go deleted file mode 100644 index 5def6f04b..000000000 --- a/config/v3_5_experimental/types/verification.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "crypto" - "encoding/hex" - "strings" - - "github.com/coreos/ignition/v2/config/shared/errors" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -// HashParts will return the sum and function (in that order) of the hash stored -// in this Verification, or an error if there is an issue during parsing. -func (v Verification) HashParts() (string, string, error) { - if v.Hash == nil { - // The hash can be nil - return "", "", nil - } - parts := strings.SplitN(*v.Hash, "-", 2) - if len(parts) != 2 { - return "", "", errors.ErrHashMalformed - } - - return parts[0], parts[1], nil -} - -func (v Verification) Validate(c path.ContextPath) (r report.Report) { - c = c.Append("hash") - if v.Hash == nil { - // The hash can be nil - return - } - - function, sum, err := v.HashParts() - if err != nil { - r.AddOnError(c, err) - return - } - var hash crypto.Hash - switch function { - case "sha512": - hash = crypto.SHA512 - case "sha256": - hash = crypto.SHA256 - default: - r.AddOnError(c, errors.ErrHashUnrecognized) - return - } - - if len(sum) != hex.EncodedLen(hash.Size()) { - r.AddOnError(c, errors.ErrHashWrongSize) - } - - return -} diff --git a/config/v3_5_experimental/types/verification_test.go b/config/v3_5_experimental/types/verification_test.go deleted file mode 100644 index 9a0914d08..000000000 --- a/config/v3_5_experimental/types/verification_test.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2020 Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "reflect" - "testing" - - "github.com/coreos/ignition/v2/config/shared/errors" - - "github.com/coreos/vcontext/path" - "github.com/coreos/vcontext/report" -) - -func TestHashParts(t *testing.T) { - tests := []struct { - in string - out error - }{ - { - `"sha512-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"`, - nil, - }, - { - `"sha256-0519a9826023338828942b081814355d55301b9bc82042390f9afaf75cd3a707"`, - nil, - }, - { - `"sha512:01234567"`, - errors.ErrHashMalformed, - }, - { - `"sha256:12345678"`, - errors.ErrHashMalformed, - }, - } - - for i, test := range tests { - fun, sum, err := Verification{Hash: &test.in}.HashParts() - if err != test.out { - t.Fatalf("#%d: bad error: want %+v, got %+v", i, test.out, err) - } - if err == nil && fun+"-"+sum != test.in { - t.Fatalf("#%d: bad hash: want %+v, got %+v", i, test.in, fun+"-"+sum) - } - } -} - -func TestHashValidate(t *testing.T) { - h1 := "xor-abcdef" - h2 := "sha512-123" - h3 := "sha512-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" - h4 := "sha256-0519a9826023338828942b081814355d55301b9bc82042390f9afaf75cd3a707" - h5 := "sha256-345" - - tests := []struct { - in Verification - out error - }{ - { - Verification{Hash: &h1}, - errors.ErrHashUnrecognized, - }, - { - Verification{Hash: &h2}, - errors.ErrHashWrongSize, - }, - { - Verification{Hash: &h3}, - nil, - }, - { - Verification{Hash: &h4}, - nil, - }, - { - Verification{Hash: &h5}, - errors.ErrHashWrongSize, - }, - } - - for i, test := range tests { - err := test.in.Validate(path.ContextPath{}) - expected := report.Report{} - expected.AddOnError(path.New("", "hash"), test.out) - if !reflect.DeepEqual(expected, err) { - t.Errorf("#%d: bad error: want %v, got %v", i, expected, err) - } - } -}