Example #1
0
 def test_URLOrPPAFormField_catches_bad_PPA_hostname(self):
     bad_url = "ppa:%s/-%s" % (
         factory.make_hostname(), factory.make_hostname())
     error = self.assertRaises(
         ValidationError, URLOrPPAFormField().clean, bad_url)
     self.assertThat(error.messages[0], Equals(
         'Enter a valid repository URL or PPA location.'))
Example #2
0
 def test_URLOrPPAFormField_catches_bad_scheme(self):
     bad_url = factory.make_url(scheme='bad_scheme')
     error = self.assertRaises(ValidationError,
                               URLOrPPAFormField().clean, bad_url)
     self.assertThat(
         error.messages[0],
         Equals('Enter a valid repository URL or PPA location.'))
Example #3
0
class PackageRepositoryForm(MAASModelForm):
    """Package Repository creation/edition form."""
    class Meta:
        model = PackageRepository
        fields = (
            'name',
            'url',
            'distributions',
            'disabled_pockets',
            'disabled_components',
            'components',
            'arches',
            'key',
            'enabled',
        )

    name = forms.CharField(label="Name",
                           required=True,
                           help_text=("The name of the Package Repository."))

    url = URLOrPPAFormField(label="Package Repository URL",
                            required=True,
                            help_text="The Package Repository URL")

    # Use UnconstrainedMultipleChoiceField fields for multiple-choices
    # fields instead of the default (djorm-ext-pgarray's ArrayFormField):
    # ArrayFormField deals with comma-separated lists and here we want to
    # handle multiple-values submissions.
    distributions = UnconstrainedMultipleChoiceField(label="Distribution list")

    disabled_pockets = UnconstrainedMultipleChoiceField(
        label="Disabled Pocket list")

    disabled_components = UnconstrainedMultipleChoiceField(
        label="Disabled Component list")

    components = UnconstrainedMultipleChoiceField(label="Component list")

    arches = UnconstrainedMultipleChoiceField(label="Architecture list")

    key = forms.CharField(
        label="Key",
        required=False,
        help_text=("The key used to authenticate the Package Repository."))

    enabled = forms.BooleanField(
        label="Enabled",
        required=False,
        help_text=("Whether or not the Package Repository is enabled."))

    def __init__(self, data=None, instance=None, request=None, **kwargs):
        super().__init__(data=data, instance=instance, **kwargs)
        if self.instance.id is None:
            self.initial['enabled'] = True
        else:
            self.fields['url'].initial = self.instance.url

    def clean(self):
        cleaned_data = super().clean()
        if self.instance.default and not cleaned_data.get('enabled', False):
            raise ValidationError("Default repositories may not be disabled.")

    def clean_arches(self):
        arches = []
        for value in self.cleaned_data.get('arches', []):
            arches.extend([s.strip() for s in value.split(',')])
        known_arches = set(PackageRepository.objects.get_known_architectures())
        for value in arches:
            if value not in known_arches:
                raise ValidationError(
                    "'%s' is not a valid architecture. Known architectures: "
                    "%s" % (value, ", ".join(sorted(known_arches))))
        # If no arches provided, use MAIN_ARCHES.
        if len(arches) == 0:
            arches = PackageRepository.MAIN_ARCHES
        return arches

    def clean_distributions(self):
        values = []
        for value in self.cleaned_data.get('distributions', []):
            values.extend([s.strip() for s in value.split(',')])
        return values

    def clean_disabled_pockets(self):
        values = []
        for value in self.cleaned_data.get('disabled_pockets', []):
            values.extend([s.strip() for s in value.split(',')])
        # This allows to reset the values of disabled_pockets if one of the
        # following is passed over the API:
        #   disabled_pockets=
        #   disabled_pockets=''
        #   disabled_pockets=None
        #   disabled_pockets=[]
        if values == [''] or values == ['None'] or values == ['[]']:
            return []
        # Check that a valid pocket is being disable.
        for pocket in values:
            if pocket not in PackageRepository.POCKETS_TO_DISABLE:
                raise ValidationError(
                    "'%s' is not a valid Ubuntu archive pocket. You "
                    "can only disable %s." %
                    (pocket, PackageRepository.POCKETS_TO_DISABLE))
        return values

    def clean_disabled_components(self):
        values = []
        for value in self.cleaned_data.get('disabled_components', []):
            values.extend([s.strip() for s in value.split(',')])
        # This allows to reset the values of disabled_components if one of the
        # following is passed over the API:
        #   disabled_components=
        #   disabled_components=''
        #   disabled_components=None
        #   disabled_components=[]
        if values == [''] or values == ['None'] or values == ['[]']:
            return []
        if self.instance is not None and not self.instance.default and values:
            raise ValidationError(
                "This is a custom repository. Please update 'components' "
                "instead.")
        # Check that a valid component is being passed.
        for component in values:
            if component not in PackageRepository.COMPONENTS_TO_DISABLE:
                raise ValidationError(
                    "'%s' is not a valid Ubuntu archive component. You "
                    "can only disable %s." %
                    (component, PackageRepository.COMPONENTS_TO_DISABLE))
        return values

    def clean_components(self):
        values = []
        for value in self.cleaned_data.get('components', []):
            values.extend([s.strip() for s in value.split(',')])
        if self.instance is not None and self.instance.default and values:
            raise ValidationError(
                "This is a default Ubuntu repository. Please update "
                "'disabled_components' instead.")
        return values
Example #4
0
 def test_URLOrPPAFormField_validates_PPA(self):
     url = "ppa:%s/%s" % (factory.make_hostname(), factory.make_hostname())
     self.assertEqual(url, URLOrPPAFormField().clean(url))
Example #5
0
 def test_URLOrPPAFormField_validates_URL(self):
     url = factory.make_url(scheme="http")
     self.assertEqual(url, URLOrPPAFormField().clean(url))
Example #6
0
 def test_rejects_none(self):
     error = self.assertRaises(ValidationError,
                               URLOrPPAFormField().clean, None)
     self.assertThat(error.message, Equals("This field is required."))
Example #7
0
class PackageRepositoryForm(MAASModelForm):
    """Package Repository creation/edition form."""
    class Meta:
        model = PackageRepository
        fields = (
            "name",
            "url",
            "distributions",
            "disabled_pockets",
            "disabled_components",
            "disable_sources",
            "components",
            "arches",
            "key",
            "enabled",
        )

    name = forms.CharField(
        label="Name",
        required=True,
        help_text="The name of the Package Repository.",
    )

    url = URLOrPPAFormField(
        label="Package Repository URL",
        required=True,
        help_text="The Package Repository URL",
    )

    # Use UnconstrainedMultipleChoiceField fields for multiple-choices
    # fields instead of the default as we want to handle
    # multiple-values submissions.
    distributions = UnconstrainedMultipleChoiceField(label="Distribution list")

    disabled_pockets = UnconstrainedMultipleChoiceField(
        label="Disabled Pocket list")

    disabled_components = UnconstrainedMultipleChoiceField(
        label="Disabled Component list")

    disable_sources = forms.BooleanField(
        label="Disable Sources",
        required=False,
        help_text="Whether or not deb-src lines are disabled.",
    )

    components = UnconstrainedMultipleChoiceField(label="Component list")

    arches = UnconstrainedMultipleChoiceField(label="Architecture list")

    key = forms.CharField(
        label="Key",
        required=False,
        help_text="The key used to authenticate the Package Repository.",
    )

    enabled = forms.BooleanField(
        label="Enabled",
        required=False,
        help_text="Whether or not the Package Repository is enabled.",
    )

    def __init__(self, data=None, instance=None, request=None, **kwargs):
        super().__init__(data=data, instance=instance, **kwargs)
        if self.instance.id is None:
            self.initial["enabled"] = True
        else:
            self.fields["url"].initial = self.instance.url

    def clean(self):
        cleaned_data = super().clean()
        if self.instance.default and not cleaned_data.get("enabled", False):
            raise ValidationError("Default repositories may not be disabled.")

    def clean_arches(self):
        arches = []
        for value in self.cleaned_data.get("arches", []):
            arches.extend([s.strip() for s in value.split(",")])
        known_arches = set(PackageRepository.objects.get_known_architectures())
        for value in arches:
            if value not in known_arches:
                raise ValidationError(
                    "'%s' is not a valid architecture. Known architectures: "
                    "%s" % (value, ", ".join(sorted(known_arches))))
        # If no arches provided, use MAIN_ARCHES.
        if len(arches) == 0:
            arches = PackageRepository.MAIN_ARCHES
        return arches

    def clean_distributions(self):
        values = []
        for value in self.cleaned_data.get("distributions", []):
            values.extend([s.strip() for s in value.split(",")])
        return values

    def clean_disabled_pockets(self):
        values = []
        for value in self.cleaned_data.get("disabled_pockets", []):
            values.extend([s.strip() for s in value.split(",")])
        # This allows to reset the values of disabled_pockets if one of the
        # following is passed over the API:
        #   disabled_pockets=
        #   disabled_pockets=''
        #   disabled_pockets=None
        #   disabled_pockets=[]
        if values == [""] or values == ["None"] or values == ["[]"]:
            return []
        # Check that a valid pocket is being disable.
        for pocket in values:
            if pocket not in PackageRepository.POCKETS_TO_DISABLE:
                raise ValidationError(
                    "'%s' is not a valid Ubuntu archive pocket. You "
                    "can only disable %s." %
                    (pocket, PackageRepository.POCKETS_TO_DISABLE))
        return values

    def clean_disabled_components(self):
        values = []
        for value in self.cleaned_data.get("disabled_components", []):
            values.extend([s.strip() for s in value.split(",")])
        # This allows to reset the values of disabled_components if one of the
        # following is passed over the API:
        #   disabled_components=
        #   disabled_components=''
        #   disabled_components=None
        #   disabled_components=[]
        if values == [""] or values == ["None"] or values == ["[]"]:
            return []
        if self.instance is not None and not self.instance.default and values:
            raise ValidationError(
                "This is a custom repository. Please update 'components' "
                "instead.")
        # Check that a valid component is being passed.
        for component in values:
            if component not in PackageRepository.COMPONENTS_TO_DISABLE:
                raise ValidationError(
                    "'%s' is not a valid Ubuntu archive component. You "
                    "can only disable %s." %
                    (component, PackageRepository.COMPONENTS_TO_DISABLE))
        return values

    def clean_components(self):
        values = []
        for value in self.cleaned_data.get("components", []):
            values.extend([s.strip() for s in value.split(",")])
        if self.instance is not None and self.instance.default and values:
            raise ValidationError(
                "This is a default Ubuntu repository. Please update "
                "'disabled_components' instead.")
        return values

    def save(self, endpoint, request):
        package_repository = super().save()
        create_audit_event(
            EVENT_TYPES.SETTINGS,
            endpoint,
            request,
            None,
            description=("%s package repository '%s'." % (
                "Updated" if self.is_update else "Created",
                package_repository.name,
            )),
        )
        return package_repository